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);
}
})
}
}

测试结果,去数据库查看

注册接口到这里就完成了

最新文章

  1. PAT 1007. 素数对猜想 (20)
  2. 关于android的单位dp与px
  3. Filco minila 的蛋疼。
  4. python 列表生成器
  5. Unity3d 在不同设备中的文件读写 的路径
  6. H - Solve this interesting problem 分类: 比赛 2015-07-29 21:06 15人阅读 评论(0) 收藏
  7. dwr入门
  8. Json工具类 - JsonUtils.java
  9. 一步步学习NHibernate(2)——配置NHibernate的环境
  10. ios save image to album
  11. cocos2d-x 发动机分析:程序如何开始和结束?
  12. 遍历Map和List的几种方法和性能比较
  13. 【BZOJ1040】【ZJOI2008】骑士
  14. 两种 js下载文件的方法(转)
  15. Quartus prime16.0 组合逻辑always块中敏感向量表不全
  16. PV、PVC和Storeclass等官方内容翻译
  17. c# 界面自适应大小
  18. mysql 内置功能 存储过程 目录
  19. Javascript开发者 常用知识
  20. MySQL数据库错误号:2003 - Can't connect to MYSQL server on 'localhost'(10061)

热门文章

  1. [转]Centos系统中查看文件和文件夹大小
  2. Java - HashCode源码解析
  3. Vue计算属性的用法
  4. 数据库导入导出expdp,impdp
  5. HTML文字闪烁
  6. 浅谈对NaN的理解
  7. Hadoop大数据初入门----haddop伪分布式安装
  8. pgAdmin4 ubuntu python 安装
  9. [基础架构]PeopleSoft Web Server 重要文件说明
  10. WOSA/XFS PTR Form解析库—头文件