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
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); } }) } }
測試結果,去數據庫查看
注冊接口到這里就完成了