关于注册和登录的各有一个问题

关于注册和登录的各有一个问题

  1. 注册方面:
    1.1 为什么注册之前要先实例化一个user才可以注册新用户(如user.py中的入口函数)?这样不就变成只有role是admin的人才有权限新建用户吗?
  2. 登录方面:
    2.1 为什么登录也是需要先实例化一个人才能登录,不是跟正常逻辑有出入吗?
    我目前尝试过使用classmethod来登录,但是由于少参数,而无法登录。
    下面是我写的代码,请老师指点迷津。
# coding: utf-8

import os
import random
import hashlib
from base import Base
from common.utils import timestamp_to_string
from common.error import (NotUserError, RoleError,
                          CountError, UserActiveError)


class User(Base):
    def __init__(self, username, user_json, gift_json):
        self.username = username
        self.gift_random = list(range(1,100))

        super().__init__(user_json, gift_json)
        self.get_user()

    def get_user(self):
        users = self._Base__read_users()

        if self.username not in users:
            raise NotUserError('not user %s' % self.username)

        current_user = users.get(self.username)

        # 对比密码 json_password数据库中的密码,u_password用户输入的密码
        json_password = current_user.get('password') # 16进制格式
        _password = self.password
        u_password = hashlib.sha1(_password.encode('utf-8')).hexdigest()
        if u_password != json_password:
            print('密码错误')
            return

        if current_user.get('active') == False:
            raise UserActiveError('%s is not active' % self.username)
        if current_user.get('role') != 'admin':
            raise RoleError('Not Admin')

        self.user = current_user
        self.name = current_user.get('username')
        self.role = current_user.get('role')
        self.gifts = current_user.get('gifts')
        self.create_time = timestamp_to_string(current_user.get('create_time'))

    # 用户注册函数
    def register(self, username, password):
        # 存储用户信息
        self._Base__write_user(username=username,
                               role='normal',
                               password=password)

    def login(self):
        username = input('please enter your username:')
        password = input('please enter your password:')
        self.get_user(username=username,password=password)

    def get_gift(self):
        gifts = self._Base__read_gifts()
        gift_lists = []

        for level_one, level_one_pool in gifts.items():  # key, value
            for level_two, level_two_pool in level_one_pool.items():
                for gift_name, gift_info in level_two_pool.items():
                    gift_lists.append(gift_info.get('name'))
        return gift_lists

    # 用户抽奖函数user.py中的choice_gift函数,当抽中函数后,实现了对相关奖品进行减少数量的操作,
    # 用base.py中__gift_update函数替代choice_gift中的功能。
    def choice_gift(self):
        self.get_user()
        # level1 get
        first_level, second_level = None, None
        # 抽第一级目录
        level_one_count = random.choice(self.gift_random)
        if 1 <= level_one_count <= 50:
            first_level = 'level1'
        elif 51 <= level_one_count <= 80:
            first_level = 'level2'
        elif 81 <= level_one_count < 95:
            first_level = 'level3'
        elif level_one_count >= 95:
            first_level = 'level4'
        else:
            raise CountError('level_one_count need 0~100')
        # 获取第一级清单
        gifts = self._Base__read_gifts()
        level_one = gifts.get(first_level)
        # 抽第二级目录
        level_two_count = random.choice(self.gift_random)

        if 1 <= level_two_count <= 80:
            second_level = 'level1'
        elif 81 <= level_two_count < 95:
            second_level = 'level2'
        elif 95 <= level_two_count <= 100:
            second_level = 'level3'
        else:
            raise CountError('level_one_count need 0~100')
        # 获取第二级清单
        level_two = level_one.get(second_level)
        if len(level_two) == 0:
            print("可惜,您没有中奖")
            return
        # 以列表的方式获取到奖品信息
        gift_names = []
        for k, _ in level_two.items():  # 忽略count,以_代替
            gift_names.append(k)

        gift_name = random.choice(gift_names)

        # 使用gift_update来替代自己写的函数
        self._Base__gift_update(first_level, second_level, gift_name)
        # 提示用户中奖了
        print('恭喜您,获得了 %s 奖品' % gift_name)

    def update(self):
        users = self._Base__read_users()
        users[self.username] = self.user

        self._Base__save(users, self.user_json)


if __name__ == "__main__":
    gift_path = os.path.join(os.getcwd(), 'storage', 'gift.json')
    user_path = os.path.join(os.getcwd(), 'storage', 'user.json')
    user = User('dewei', user_path, gift_path)
    user.register(username='xuhaoyan',password='xhy123123')

# coding: utf-8

import os
import json
import time
import hashlib
import multiprocessing
from common.utils import check_file, timestamp_to_string
from common.error import (UserExistsError, RoleError,
                          LevelError, NegativeNumberError, CountError)  # 用户存在报错提示
from common.consts import ROLES, FIRSTLEVELS, SECONDLEVELS


class Base(object):
    def __init__(self, user_json, gift_json):
        self.user_json = user_json
        self.gift_json = gift_json

        self.__check_user_json()
        self.__check_gift_json()
        self.__init_gifts()
        # 防止并发思路:在对user.json, gift.json两个文件的删除,
        # 修改以及添加三个相关函数并添加进程锁,从而防止并发。
        manager = multiprocessing.Manager()
        self.lock = manager.Lock()

    def __check_user_json(self):
        check_file(self.user_json)

    def __check_gift_json(self):
        check_file(self.gift_json)

    def __read_users(self, time_to_str=False):
        with open(self.user_json, 'r') as f:
            data = json.loads(f.read())

        if time_to_str == True:
            for username, v in data.items():
                v['create_time'] = timestamp_to_string(v['create_time'])
                v['update_time'] = timestamp_to_string(v['update_time'])
                data[username] = v
        return data  # 返回的应该是字典类型的数据

    # 创建用户信息
    def __write_user(self, **user):
        if 'username' not in user:
            raise ValueError('missing username')
        if 'role' not in user:
            raise ValueError('missing role')

        # 以hashlib的方式存入密码
        # 对password进行比特类型转encode
        hashcode = hashlib.sha1(user['password'].encode('utf-8'))
        # 生成16进制加密串
        _token = hashcode.hexdigest()

        # user['active'] = True
        user['active'] = False
        user['create_time'] = time.time()
        user['update_time'] = time.time()
        user['gifts'] = []
        user['password'] = _token

        users = self.__read_users()
        if user['username'] in users:
            raise UserExistsError('username %s 已存在' % user['username'])

        users.update(
            {user['username']: user}   # {'dewei':{username:...}}
        )
        self.__save(users, self.user_json)
        # json_users = json.dumps(users)
        # with open(self.user_json, 'w') as f:
        #     f.write(json_users)

    def __change_role(self, username, role):
        users = self.__read_users()
        user = users.get(username)
        if not user:
            return False

        if role not in ROLES:
            raise RoleError('not user role %s' % role)

        user['role'] = role  # 不能随便修改
        user['update_time'] = time.time()
        users[username] = user

        self.__save(users, self.user_json)

    def __change_active(self, username):
        users = self.__read_users()
        user = users.get(username)
        if not user:
            return False

        user['active'] = not user['active']
        user['update_time'] = time.time()
        users[username] = user

        self.__save(users, self.user_json)
        return True

    def __delete_user(self, username):
        users = self.__read_users()
        user = users.get(username)
        if not user:
            return False

        delete_user = users.pop(username)

        self.__save(users, self.user_json)
        return delete_user

    def __read_gifts(self):
        with open(self.gift_json) as f:
            data = json.loads(f.read())
        return data

    def __init_gifts(self):
        data = {
            'level1':{
                'level1':{},
                'level2':{},
                'level3':{}
            },
            'level2': {
                'level1': {},
                'level2': {},
                'level3': {}
            },
            'level3': {
                'level1': {},
                'level2': {},
                'level3': {}
            },
            'level4': {
                'level1': {},
                'level2': {},
                'level3': {}
            }
        }
        gifts = self.__read_gifts()
        if len(gifts) != 0:
            return
        self.__save(data, self.gift_json)

    def __check_and_getgift(self, first_level, second_level, gift_name):

        if first_level not in FIRSTLEVELS:
            raise LevelError('firstlevel does not exist')
        if second_level not in SECONDLEVELS:
            raise LevelError('secondlevel does not exist')

        gifts = self.__read_gifts()
        level_one = gifts[first_level]  # 获取了level1的level
        level_two = level_one[second_level]

        if gift_name not in level_two:
            return False

        return{
            'level_one': level_one,
            'level_two': level_two,
            'gifts': gifts
         }

    def __write_gifts(self, first_level, second_level,
                    gift_name, gift_count):

        if first_level not in FIRSTLEVELS:
            raise LevelError('firstlevel does not exist')
        if second_level not in SECONDLEVELS:
            raise LevelError('secondlevel does not exist')

        gifts = self.__read_gifts()

        current_gift_pool = gifts[first_level]
        current_second_gift_pool = current_gift_pool[second_level]

        if gift_count <= 0:
            gift_count = 1

        if gift_name in current_second_gift_pool:
            current_second_gift_pool[gift_name]['count'] = \
                current_second_gift_pool[gift_name]['count'] + gift_count
        else:
            current_second_gift_pool[gift_name] = {
                'name': gift_name,
                'count': gift_count
            }

        gifts[first_level] = current_gift_pool
        current_gift_pool[second_level] = current_second_gift_pool

        self.__save(gifts, self.gift_json)

    def __gift_update(self, first_level, second_level,
                    gift_name, gift_count=1, is_admin=False):
        assert isinstance(gift_count, int), 'gift count is an int'
        data = self.__check_and_getgift(first_level, second_level, gift_name)
        if data == False:
            return data

        current_gift_pool = data.get('level_one')
        current_second_gift_pool = data.get('level_two')
        gifts = data.get('gifts')

        if gift_name not in current_second_gift_pool:
            return False

        current_gift = current_second_gift_pool[gift_name]
        # 判断用户是不是admin权限
        if is_admin == True:
            if gift_count <= 0:
                # raise CountError('gift_count can not be zero')
                print('可惜,奖品没有了')
            current_gift['count'] = gift_count
        else:
            if current_gift['count'] - gift_count< 0:
                return NegativeNumberError('gift count can not be negative')
            current_gift['count'] -= gift_count

        # 奖品数量变动后,将整个字典传入
        current_second_gift_pool[gift_name] = current_gift
        current_gift_pool[second_level] = current_second_gift_pool
        gifts[first_level] = current_gift_pool

        self.__save(gifts, self.gift_json)

    def __delete_gift(self, first_level, second_level, gift_name):
        data = self.__check_and_getgift(first_level, second_level, gift_name)
        if data == False:
            return data

        current_gift_pool = data.get('level_one')
        current_second_gift_pool = data.get('level_two')
        gifts = data.get('gifts')

        delete_gift_data = current_second_gift_pool.pop(gift_name)
        current_gift_pool[second_level] = current_second_gift_pool
        gifts[first_level] = current_gift_pool
        self.__save(gifts, self.gift_json)
        return delete_gift_data

    def __save(self, data, path):
        json_data = json.dumps(data)
        # 创建锁,防止并发,最后无论如何锁打开
        try:
            self.lock.acquire()
            with open(path, 'w') as f:
                f.write(json_data)
        finally:
            self.lock.release()

正在回答 回答被采纳积分+1

登陆购买课程后可参与讨论,去登陆

1回答
好帮手慕燕燕 2021-04-09 16:49:28

同学,你好!

1、注册用户并非要先实例化一个user类,可以自定义一个用户注册类RegistUser类,实现用户注册功能,并不是要求角色为admin的人新建用户,同学可参考以下代码:

http://img1.sycdn.imooc.com//climg/606ffbe30926684710110767.jpg

2、User类的init方法中调用了get_user()方法,实例化User类,类中的init方法被自动执行,也就执行了里面的get_user()方法,而get_user()方法实现用户的登录功能,因此登录要先实例化User类

http://img1.sycdn.imooc.com//climg/606ffc7d09cd11bd10070348.jpg

3、同学的User类init方法缺少password参数,判断密码时使用self.password会提示缺少参数

http://img1.sycdn.imooc.com//climg/60701441099d2d4109880294.jpg

4、判断密码可参考以下写法:

http://img1.sycdn.imooc.com//climg/607014ca09851df909330469.jpg

5、实例化User类时也需要传入密码

http://img1.sycdn.imooc.com//climg/6070150c09bc2d8109670195.jpg

祝:学习愉快!


  • 提问者 三姐四哥五弟 #1

    非常感谢老师写得这么详细。

    我想第一点可能是我问得有些问题,如果说按照作业题中的要求,新建一个注册函数,而不是新建一个注册类的话,是不是意味着只有管理员才能创建新用户。

    第五点,由于加入了password字段,在user.json文件中,原本所有的user都没有password字段,我在重新实例化的过程中,遇到缺乏password字段,是不是应该先对原先的各个user添加password字段?

    2021-04-10 10:28:19
  • 同学,你好!

    1、新建一个注册函数,不是新建一个注册类的话,并不意味着只有管理员才能创建用户,非管理员也可以创建用户,登录成功就可以。但这不符合逻辑,如果将注册函数写在User类中,实例化User类,init函数调用get_user函数,实现的是登录功能,登录之后再去注册新用户,而通常的业务逻辑是先注册后登录。

    2、是的,user.json文件中,需要添加password字段,登录过程中输入的密码要和读取的密码进行比对,读取不到就会提示缺少参数。

    祝:学习愉快!

    2021-04-10 13:39:37
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师