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

測試結果,去數據庫查看

注冊接口到這里就完成了

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM