zoukankan      html  css  js  c++  java
  • 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

    测试结果,去数据库查看

    注册接口到这里就完成了

  • 相关阅读:
    IIS的各种身份验证详细测试
    HTTP Error 401.3 Unauthorized Error While creating IIS 7.0 web site on Windows 7
    C/S and B/S
    WCF ContractFilter mismatch at the EndpointDispatcher exception
    Configure WCF
    Inheritance VS Composition
    Unhandled Error in Silverlight Application, code 2103 when changing the namespace
    Java RMI VS TCP Socket
    Principles Of Object Oriented Design
    Socket处理发送和接收数据包,一个小实例:
  • 原文地址:https://www.cnblogs.com/blog-rui/p/9742266.html
Copyright © 2011-2022 走看看