• Django商城项目笔记No.8用户部分-注册接口实现


    Django商城项目笔记No.8用户部分-注册接口实现

    users的view.py中增加如下代码

    class RegisterUserView(CreateAPIView):
        """
        用户注册视图
        """
        serializer_class = serializers.RegisterUserSerializer

    在users中创建serializers.py

    class RegisterUserSerializer(serializers.ModelSerializer):
        """用户注册序列化器"""
        password2 = serializers.CharField(label='确认密码', write_only=True)
        sms_code = serializers.CharField(label='短信验证码', write_only=True)
        allow = serializers.CharField(label='同意协议', write_only=True)
    
        class Meta:
            model = User
            fields = ('id', 'username', 'password', 'password2', 'sms_code', 'mobile', 'allow')
            extra_kwargs = {
                'username': {
                    'min_length': 5,
                    'max_length': 20,
                    'error_messages': {
                        'min_length': '仅允许5-20个字符的用户名',
                        'max_length': '仅允许5-20个字符的用户名',
                    }
                },
                'password': {
                    'write_only': True,
                    'min_length': 8,
                    'max_length': 20,
                    'error_messages': {
                        'min_length': '仅允许8-20个字符的密码',
                        'max_length': '仅允许8-20个字符的密码',
                    }
                }
            }
    
        def validate_mobile(self, value):
            """验证手机号"""
            if not re.match(r'^1[3-9]d{9}$', value):
                raise serializers.ValidationError('手机号格式错误')
            return value
    
        def validate_allow(self, value):
            """检查用户是否同意协议"""
            if value != 'true':
                raise serializers.ValidationError('请同意用户协议')
            return value
    
        def validate(self, attrs):
            # 判断两次密码
            if attrs['password'] != attrs['password2']:
                raise serializers.ValidationError('输入的两次密码不一致')
    
            # 判断短信验证码
            redis_conn = get_redis_connection('verify_codes')
            # 获取真实验证码
            real_sms_code = redis_conn.get('sms_%s' % attrs['mobile'])
            # 如果取出来是None,那么代表已经超时了
            if real_sms_code is None:
                raise serializers.ValidationError('短信验证码无效')
            # 注意real_sms_code 从redis中取出来的是bytes类型,需要decode一下
            if attrs['sms_code'] != real_sms_code.decode():
                raise serializers.ValidationError('短信验证码错误')
    
            return attrs
    
        def create(self, validated_data):
            """重写保存方法,增加密码加密"""
    
            # 移除数据库模型类中不需要的属性
            # 删除字典数据的两种方法是
            # del 字典[key] 删除指定键值对,key不存在不会报错
            # 字典.pop(key) 删除指定键值对,key不存在会报错
            del validated_data['password2']
            del validated_data['allow']
            del validated_data['sms_code']
    
            # user = User.objects.create(username=xxx, password=xxxx, mobile=xxxx)
            user = User.objects.create(**validated_data)
    
            # 将密码加密,然后保存
            user.set_password(validated_data['password'])
            user.save()
    
            return user
    View Code
    fields = ('id', 'username', 'password', 'password2', 'sms_code', 'mobile', 'allow')

    fields=(),括号里面需要输入序列化和反序列化过程中所用到的所有字段,如果是模型类中没有的字段,可以在上面指明字段的类型和限制

    password2 = serializers.CharField(label='确认密码', write_only=True)
    sms_code = serializers.CharField(label='短信验证码', write_only=True)
    allow = serializers.CharField(label='同意协议', write_only=True)

    write_only=True的意思是指在序列化的时候使用,序列化(从后端往前端传叫序列化),反序列化(从前端往后端传,保存到数据库中,叫反序列化)

    extra_kwargs = {
                'username': {
                    'min_length': 5,
                    'max_length': 20,
                    'error_messages': {
                        'min_length': '仅允许5-20个字符的用户名',
                        'max_length': '仅允许5-20个字符的用户名',
                    }
                },
                'password': {
                    'write_only': True,
                    'min_length': 8,
                    'max_length': 20,
                    'error_messages': {
                        'min_length': '仅允许8-20个字符的密码',
                        'max_length': '仅允许8-20个字符的密码',
                    }
                }

    extra_kwargs是对字段做限制。“error_messages”是如果不符合限制的规则,提示的信息

    def validate_mobile(self, value):
        """验证手机号"""
        if not re.match(r'^1[3-9]d{9}$', value):
            raise serializers.ValidationError('手机号格式错误')
        return value

    validate_字段名,是对一个字段做判断。自己写判断规则,如果不符合的话,就抛出异常,最后再return value

    def validate(self, attrs): 这是对多个字段做判断,attrs是一个字典,可以通过attrs['字段名']来获取字段的值

    不符合的话,也是raise 抛出异常,最后再return attrs


     最后重写create方法,创建user

    创建之前要把数据库模型类中不需要的字段从validated_data中删掉

    # 移除数据库模型类中不需要的属性
    # 删除字典数据的两种方法是
    # del 字典[key] 删除指定键值对,key不存在不会报错
    # 字典.pop(key) 删除指定键值对,key不存在会报错

    这里使用del删除

    del validated_data['password2']
    del validated_data['allow']
    del validated_data['sms_code']

    删除之后,validated_data字典中只剩下这几个'id', 'username', 'password', 'mobile' 键值对  TODO?


    为什么要重写create方法,

    user = User.objects.create(username=xxx, password=xxxx, mobile=xxxx)

    user = User.objects.create(**validated_data)  # **validated_data是拆包,拆成上面的形式

    因为password字段,需要存入的是加密后的密码,如果直接create()然后save()的话,存入的密码是明文,所以要调用user.set_password(validated_data['password'])

    加密密码之后再进行save保存,然后return user


    设置路由

    前端js代码

            // 注册
            on_submit: function(){
                this.check_username();
                this.check_pwd();
                this.check_cpwd();
                this.check_phone();
                this.check_sms_code();
                this.check_allow();
    
                if(this.error_name == false && this.error_password == false && this.error_check_password == false 
                    && this.error_phone == false && this.error_sms_code == false && this.error_allow == false) {
                    axios.post(this.host + '/users/', {
                            username: this.username,
                            password: this.password,
                            password2: this.password2,
                            mobile: this.mobile,
                            sms_code: this.sms_code,
                            allow: this.allow.toString()
                        }, {
                            responseType: 'json'
                        })
                        .then(response => {
                            location.href = '/index.html';    
                        })
                        .catch(error=> {
                            if (error.response.status == 400) {
                                if ('non_field_errors' in error.response.data) {
                                    this.error_sms_code_message = error.response.data.non_field_errors[0];
                                } else {
                                    this.error_sms_code_message = '数据有误';
                                }
                                this.error_sms_code = true;
                            } else {
                                console.log(error.response.data);
                            }
                        })
                }
            }
    View Code

    测试结果,去数据库查看

    注册接口到这里就完成了

  • 相关阅读:
    java工作复习——执行JS脚本——滚动条01
    java工作复习——cookie的增删查
    java工作复习——4大时间等待——显示等待(转载)
    java工作复习——4大时间等待——显示等待
    java工作复习——4大时间等待——隐式等待等待(driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);)
    java工作复习——4大时间等待——强制等待(Thread.sleep(5000);)
    java工作复习——键盘事件——action类——复制、粘贴 (转载)
    java工作复习——键盘事件——action类——复制、粘贴
    java工作复习——鼠标事件——action类——转载总结
    java工作复习——鼠标事件——action类——模拟鼠标从一个位置移动到另外一个位置
  • 原文地址:https://www.cnblogs.com/blog-rui/p/9742266.html
Copyright © 2020-2023  润新知