一、注冊功能(完)
1.業(yè)務流程分析
- 對校驗進行校驗
- 校驗用戶名
- 校驗密碼
- 校驗手機號碼
- 校驗短信驗證碼
- 新建數(shù)據(jù)庫記錄
2、接口設計
2.1 接口說明
| 條目 | 說明 |
|---|---|
| 請求方法 | POST |
| url定義 | /user/register/ |
| 參數(shù)格式 | 表單(form) |
2.2 參數(shù)說明
| 參數(shù)名字 | 類型 | 是否必須 | 描述 |
|---|---|---|---|
| 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
# 調用模板 檢驗數(shù)據(jù) 創(chuàng)建數(shù)據(jù)庫記錄
def post(self,request):
# 1. 校驗數(shù)據(jù)
form = RegisterForm(request.POST)
if form.is_valid():
# 2. 創(chuàng)建數(shù)據(jù)庫記錄
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):
'''
校驗密碼(聯(lián)合校驗)
:return:
'''
clean_data = super().clean()
password = clean_data.get('password')
password_repeat = clean_data.get('password_repeat')
##################################
if password != password_repeat:
raise forms.ValidationError('兩次輸入的密碼不一致,請重新輸入')
######################################
# 如果上面這個判斷驗證不通過,下面代碼不會執(zhí)行
###################################
## 校驗短信驗證碼
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 的區(qū)別
clean_字段名: 你寫多少就執(zhí)行多少 記得要return 字段名
clean: 只要有一部分不通過就不會往下執(zhí)行
4. 前端部分
// 6. 注冊
let $submitBtn = $('.register-btn');
$submitBtn.click((e)=>{
//阻止默認提交
e.preventDefault();
//檢查各參數(shù)狀態(tài)
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位數(shù)字');
return
}
// 發(fā)送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
#發(fā)送的代碼
ccp = CCP()
try:
res = ccp.send_template_sms(mobile, [sms_code, constants.SMS_CODE_EXPIRES], "1")
if res == 0:
logger.info('發(fā)送短信驗證碼[正常][mobile: %s sms_code: %s]' % (mobile, sms_code))
else:
logger.error('發(fā)送短信驗證碼[失敗][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('發(fā)送短信驗證碼[異常][mobile: %s message: %s]' % (mobile, e))
return json_response(errno=Code.SMSERROR, errmsg=error_map[Code.SMSERROR])
附上效果圖

01.jpg

02.jpg

03.jpg

04.jpg
最后的最后
$ git add .
$ git commit -m 'update projects'
$ git push origin master