一、注册功能(完)
1.业务流程分析
- 对校验进行校验
- 校验用户名
- 校验密码
- 校验手机号码
- 校验短信验证码
- 新建数据库记录
2、接口设计
2.1 接口说明
条目 | 说明 |
---|---|
请求方法 | POST |
url定义 | /user/register/ |
参数格式 | 表单(form) |
2.2 参数说明
参数名字 | 类型 | 是否必须 | 描述 |
---|---|---|---|
username | 字符串 | 是 | 用户输入的用户名 |
password | 字符串 | 是 | 用户输入的密码 |
password_repeat | 字符串 | 是 | 用户输入的重复(确认)密码 |
monile | 字符串 | 是 | 用户输入的手机号码 |
sms_code | 字符串 | 是 | 用户输入的短信验证码 |
注意每个表单页面都要自己加 {% csrf_token %}
2.3 返回的结果:
返回的结果:
{
"errno":"0",
"errmsg":"恭喜您,注册成功~!",
}
3.编写代码
既然是框架就要符合框架的逻辑,视图的views 只调用相应的模板即可,校验在forms 表单校验,因此 在 user 下面新建forms.py
user_views 新增代码
......
from .forms import RegisterForm
from utils.res_code import json_response,Code
from .models import User
# 调用模板 检验数据 创建数据库记录
def post(self,request):
# 1. 校验数据
form = RegisterForm(request.POST)
if form.is_valid():
# 2. 创建数据库记录
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
mobile = form.cleaned_data.get('mobile')
User.objects.create_user(username=username,password=password,mobile=mobile)
return json_response(errmsg='恭喜您注册成功,请愉快玩耍~')
else:
# 将失败信息进行拼接
err_msg_list = []
for item in form.errors.values():
# item 也是一个列表,所以把错误信息放在item的第一位
err_msg_list.append(item[0])
err_msg_str = '/'.join(err_msg_list)
return json_response(errno=Code.PARAMERR, errmsg=err_msg_str)
user_forms 代码:
from django import forms
from django_redis import get_redis_connection
from verification import constants
from .models import User
from verification.forms import mobile_validator
class RegisterForm(forms.Form):
'''
用户注册表单
'''
# 获取字段内容
username = forms.CharField(label='用户名',max_length=20,min_length=5,error_messages={
'max_length':'用户名长度要小于20',
'min_length':'用户名长度至少5个字符',
'required':'用户名不能为空',
})
password = forms.CharField(label='密码', max_length=20, min_length=6, error_messages={
'max_length': '密码长度要小于20',
'min_length': '密码长度至少6个字符',
'required': '密码不能为空',
})
password_repeat = forms.CharField(label='重复密码', max_length=20, min_length=6, error_messages={
'max_length': '密码长度要小于20',
'min_length': '密码长度至少6个字符',
'required': '密码不能为空',
})
mobile = forms.CharField(label='手机号码', max_length=11, min_length=11,validators=[mobile_validator,], error_messages={
'max_length': '请输入正确的11位手机号码',
'min_length': '请输入正确的11位手机号码',
'required': '手机号码不能为空',
})
sms_code = forms.CharField(label='短信验证码', max_length=constants.SMS_CODE_LENGTH, min_length=constants.SMS_CODE_LENGTH, error_messages={
'max_length': '短信验证码长度不正确',
'min_length': '短信验证码长度不正确',
'required': '短信验证码不能为空',
})
##校验从这里开始
def clean_username(self):
'''
校验用户名
:return:
'''
username = self.cleaned_data.get('username')
if User.objects.filter(username=username).exists():
raise forms.ValidationError('用户名已注册,请重新输入')
return username
def clean_mobile(self):
'''
校验手机号码
:return:
'''
mobile = self.cleaned_data.get('mobile')
if User.objects.filter(mobile=mobile).exists():
raise forms.ValidationError('手机号码已注册,请重新输入')
return mobile
def clean(self):
'''
校验密码(联合校验)
:return:
'''
clean_data = super().clean()
password = clean_data.get('password')
password_repeat = clean_data.get('password_repeat')
##################################
if password != password_repeat:
raise forms.ValidationError('两次输入的密码不一致,请重新输入')
######################################
# 如果上面这个判断验证不通过,下面代码不会执行
###################################
## 校验短信验证码
sms_code = clean_data.get('sms_code')
mobile = clean_data.get('mobile')
redis_conn = get_redis_connection(alias='verify_code')
real_code = redis_conn.get('sms_text_%s'%(mobile))
print(real_code,' ',sms_code)
if (not real_code) or ( real_code.decode('utf-8') != sms_code ) :
raise forms.ValidationError('短信验证码错误')
这里注意一点: clean_字段名 跟 clean 的区别
clean_字段名:
你写多少就执行多少 记得要return 字段名
clean:
只要有一部分不通过就不会往下执行
4. 前端部分
// 6. 注册
let $submitBtn = $('.register-btn');
$submitBtn.click((e)=>{
//阻止默认提交
e.preventDefault();
//检查各参数状态
if (!isUsernameReady) {
fnCheckUsername();
return
}
if (!isPasswordReady){
fnCheckPassword();
return
}
if (!isMobileReady){
fnCheckMobile();
return
}
// 检验短信验证码
let sSmsCode = $('input[name="sms_captcha"]').val();
if (sSmsCode === ''){
message.showError('短信验证码不能为空,请重新输入');
return
}
if (!(/^\d{4}$/).test(sSmsCode)){
message.showError('短信验证码长度不正确,必须是4位数字');
return
}
// 发送ajax
$
.ajax({
url:'/user/register/',
type:'POST',
data:{
mobile : $mobile.val(),
username:$username.val(),
password:$('input[name="password"]').val(),
password_repeat:$passwordRepeat.val(),
sms_code:sSmsCode,
},
dataType:'json',
})
.done((res)=>{
if(res.errno === '0'){
message.showSuccess(res.errmsg);
//跳转的登录页面
setTimeout(()=>{
window.location.href='/user/login/'
},1500)
}else {
//注册失败
message.showError(res.errmsg);
}
})
.fail((res)=>{
message.showError('服务器连接超时,请重试');
})
})
5.短信验证码
在 verification_views 之前留下的接口处增加以下代码
# 新增导入包
from utils.yuntongxun.sms import CCP
#发送的代码
ccp = CCP()
try:
res = ccp.send_template_sms(mobile, [sms_code, constants.SMS_CODE_EXPIRES], "1")
if res == 0:
logger.info('发送短信验证码[正常][mobile: %s sms_code: %s]' % (mobile, sms_code))
else:
logger.error('发送短信验证码[失败][moblie: %s sms_code: %s]' % (mobile, sms_code))
return json_response(errno=Code.SMSFAIL, errmsg=error_map[Code.SMSFAIL])
except Exception as e:
logger.error('发送短信验证码[异常][mobile: %s message: %s]' % (mobile, e))
return json_response(errno=Code.SMSERROR, errmsg=error_map[Code.SMSERROR])
附上效果图
最后的最后
$ git add .
$ git commit -m 'update projects'
$ git push origin master