用户注册单个字段的功能已经实现,现在就是完成提交注册功能的实现。
提交注册功能和短信功能实现过程是一模一样的,只是字段验证多一些。
一、urls.py配置
users/urls.py
from django.urls import path
from users import views
urlpatterns = [
path("register/", views.RegisterView.as_view(), name="register"),
]
二、views.py逻辑处理
import json
import logging
from django.views import View
from django.shortcuts import render
from django.contrib.auth import login
from users import models
from users.forms import RegisterForm
from utils.res_code.res_code import Code, error_map
from utils.res_code.json_function import to_json_data
logger = logging.getLogger("django")
class RegisterView(View):
# 1. 创建一个类
"""
username 用户名
password 密码
password_repeat 确认密码
mobile 电话号码
sms_text 短信验证码
"""
# 2. 创建一个get方法,来跳转页面
def get(self, request):
return render(request, 'users/register.html')
# 3. 创建一个post方法来处理逻辑
def post(self, request):
# 4. 获取前端传来的数据
try:
json_data = request.body
if not json_data:
return to_json_data(errno=Code.PARAMERR, errmsg=error_map[Code.PARAMERR])
dict_data = json.loads(json_data)
except Exception as e:
# logger.info("注册错误:{}".format(e)) # 调试用
return to_json_data(errno=Code.UNKOWNERR, errmsg=error_map[Code.UNKOWNERR])
# 5. 将数据转化为字典并传入到RegisterForm表单里面
form = RegisterForm(data=dict_data)
# 6. RegisterForm验证成功后获取到校验后的的数据
if form.is_valid():
username = form.cleaned_data.get("username")
mobile = form.cleaned_data.get("mobile")
password = form.cleaned_data.get("password")
password_repeat = form.cleaned_data.get("password_repeat")
# 7. 判断密码和确认密码是否一致
if password != password_repeat:
return to_json_data(errmsg="密码前后不一致,请重新输入!")
# 8. 将用户信息保存到数据库
user = models.Users.objects.create_user(username=username, mobile=mobile, password=password)
# 9. 跳转到登录页面
login(request, user)
# 返回数据到前端
return to_json_data(errmsg="恭喜您注册成功")
else:
err_msg_list = []
for item in form.errors.values():
err_msg_list.append(item[0])
err_str = "/".join(err_msg_list)
return to_json_data(errmsg=err_str)
三、forms.py表单验证
# -*- coding: utf-8 -*-
"""
@Time : 2020/2/27 15:02
@Author : 半纸梁
@File : forms.py
"""
from django import forms
from users import models
from django_redis import get_redis_connection
class RegisterForm(forms.Form):
"""
register field verify
"""
# 1. 单字段验证
username = forms.CharField(
max_length=18,
min_length=6,
error_messages={
"max_length": "用户名格式不正确",
"min_length": "用户名格式不正确",
"required": "用户名不能为空"
}
)
password = forms.CharField(
max_length=20,
min_length=6,
error_messages={
"max_length": "密码格式不正确",
"min_length": "密码格式不正确",
"required": "密码不能为空"
}
)
password_repeat = forms.CharField(
max_length=20,
min_length=6,
error_messages={
"max_length": "密码格式不正确",
"min_length": "密码格式不正确",
"required": "密码不能为空"
}
)
mobile = forms.CharField(
max_length=11,
min_length=11,
error_messages={
"max_length": "手机号格式不正确",
"min_length": "手机号格式不正确",
"required": "手机号不能为空"
}
)
sms_text = forms.CharField(
max_length=6,
min_length=6,
error_messages={
"max_length": "短信验证码格式不正确",
"min_length": "短信验证码格式不正确",
"required": "短信验证码不能为空"
}
)
# 2. 校验用户名是否已被注册
def clean_username(self):
cleaned_username = self.cleaned_data.get("username")
if models.Users.objects.filter(username=cleaned_username).exists():
raise forms.ValidationError("用户名已经被注册,请重新输入")
return cleaned_username
# 3. 校验手机号是否已被注册
def clean_mobile(self):
cleaned_mobile = self.cleaned_data.get("mobile")
if models.Users.objects.filter(mobile=cleaned_mobile).exists():
raise forms.ValidationError("手机号已被注册,请重新输入")
return cleaned_mobile
# 4. 联合校验获取到清洗后的数据
def clean(self):
cleaned_data = super().clean()
cleaned_password = cleaned_data.get("password")
cleaned_password_repeat = cleaned_data.get("password_repeat")
cleaned_mobile = cleaned_data.get("mobile")
cleaded_sms_code = cleaned_data.get("sms_text")
# 5. 判断密码和确认密码是一致
if cleaned_password != cleaned_password_repeat:
raise forms.ValidationError("密码输入不一致,请重新输入")
# 6. 判断短信验证码是否和redis中的一致
redis_obj = get_redis_connection("verify_code")
sms_key = "sms_code_{}".format(cleaned_mobile).encode("utf8")
redis_sms_text = redis_obj.get(sms_key)
if (not redis_sms_text) or (cleaded_sms_code != redis_sms_text.decode("utf8")):
raise forms.ValidationError("短信验证码不正确,请重新输入")
四、js前端实现
$(function () {
let $username = $('#user_name'); //获取用户名标签
let $register = $(".form-contain"); //form表单所有元素 不能获取到submit按钮那里去
//注册
$register.submit(function(res){
//阻止默认提交操作
res.preventDefault();
//获取用户输入的内容
let sUsername = $username.val(); // 用户输入的用户名
let sPassword = $("input[name=password]").val(); //用户输入的密码
let sPasswordRepeat = $("input[name=password_repeat]").val(); //用户输入的确认密码
let sMobile = $mobile.val(); //用户输入的手机号码
let sSmsCode = $("input[name=sms_captcha]").val(); //短信验证码
//前端对前面5项进行判定
//判断用户名是否已被注册
if (fn_check_username() !=="success"){
//alert("用户已被注册,请重新输入");
return
}
//判断手机号是否已被注册
if(fn_check_mobile() !=="success"){
return
}
//判断密码或者确认密码是否为空
if((!sPassword) || (!sPasswordRepeat)){
alert("密码或者用户密码不能为空");
return
}
//判断密码和确认密码长度是否合适
if ((sPassword.length<6 || sPassword.length>20)||(sPasswordRepeat.length<6 || sPasswordRepeat.length>20)){
alert("密码长度不在6-20范围内");
return
}
//判断密码和确认密码是否一致
if(sPassword !== sPasswordRepeat){
alert("两次输入的密码不一致");
return
}
//判断短信验证码输入位数是否为6位
if(!(/^\d{6}$/).test(sSmsCode)){
alert("短信验证码长度不正确");
return
}
//发起注册
//1.注册参数
let sDataParams ={
"username": sUsername,
'mobile': sMobile,
'password': sPassword,
'password_repeat': sPasswordRepeat,
'sms_text': sSmsCode,
};
//创建ajax请求
$.ajax({
url:"/users/register/", //请求地址
type:"POST", //请求类型
data:JSON.stringify(sDataParams), //请求参数
contentType:"application/json;charset=utf-8", //请求数据类型前端发送给后端的
dataType:"json", //后端返回给前端的数据类型
success:function (arg) {
if(arg.errno==="200"){
alert("恭喜注册成功");
setTimeout(function(){
window.location.href = "/users/login/"; //注册成功后跳转到登录界面 document.referrer 回到上一个页面
},1500);
}else{
alert("注册失败:"+arg.errmsg)
}
},
error:function () {
alert("注册ajax,服务器超时,请重试")
}
})
});
}
);
五、register.js前端代码汇总
$(function () {
let $img = $('.form-item .captcha-graph-img img'); //获取图片信息
let sImageCodeId=''; //定义一个空字符串用来放uuid字符串
let $username = $('#user_name'); //获取用户名标签
let $mobile = $("#mobile"); //获取手机号
let $smsCodeBtn = $(".form-item .sms-captcha"); //发送短信验证按钮
let $smsCodeText = $(".form-item .form-captcha"); //图形验证码输入框文本
let $register = $(".form-contain"); //form表单所有元素 不能获取到submit按钮那里去
generateImageCode();
// 当点击验证码时刷新验证码
$img.click(generateImageCode);
// 生成图片UUID验证码
function generateUUID() {
let d = new Date().getTime();
if (window.performance && typeof window.performance.now === "function") {
d += performance.now(); //use high-precision timer if available
}
let uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
let r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c==='x' ? r : (r & 0x3 | 0x8)).toString(16);
});
return uuid;
}
//生成验证码图片
function generateImageCode() {
sImageCodeId = generateUUID(); //这里不能有let这相当于对前面的sImageCodeId进行修改
// console.log("第一个uuid:"+sImageCodeId);
let imageCodeUrl = '/image_code/'+sImageCodeId+'/'; //拼接图片验证码请求路径
$img.attr('src',imageCodeUrl); //给图片添加src链接 路径
}
//鼠标移出用户名输入框时执行判断
$username.blur(function () {
fn_check_username();
});
// 用户名是否存在
function fn_check_username() {
let sUsername = $username.val(); //获取表单数据
let sReturnValue = '';
// 前端校验不
if (sUsername === ""){
// alert("用户名不能为空") ;
// message.showError('用户名能为空!');
// alert('用户名能为空!'); //这里需要改进
return
}else if(!(/\w{5,18}/).test(sUsername)){
// message.showError('请输入6~18位字符的用户名!');
// alert('请输入6~18位字符的用户名!'); //这里需要改进
return
}
//ajax请求判断数据库是否存在 后端校验
$.ajax({
url:'/username/' + sUsername +'/',
type:'GET',
dataType:'json',
async: false,
//这里可以使用.done和.fale两个函数俩写返回成功和返回失败
success:function (arg) {
if(arg.data.count !== 0){ // 不等于0表示已经注册了
// alert("用户名已注册,请重新输入")
sReturnValue = "";
}else{
sReturnValue="success";
alert("用户名可以正常使用")
}
},
error:function(){
alert("用户名ajax,服务器超时,请重新输入");
sReturnValue = "";
}
});
return sReturnValue //返回出该信息
}
//鼠标移出手机号输入框时执行判断
$mobile.blur(function() {
fn_check_mobile();
});
// 手机号是否存在
function fn_check_mobile(){
let sMobile = $mobile.val();
let sReturnMobileValue = "";
// 前端校验
if (sMobile === ""){
// alert("手机号输入为空");
alert("手机号为空");
}else if(!(/^1[3-9]\d{9}/).test(sMobile)){
alert("请输入正确的手机号格式") ;
}
//ajax请求判断数据库是否存在 后端校验
$.ajax({
url:"/mobile/"+sMobile+'/',
type:"GET",
dataType: "json",
async:false, // 关闭异步
success:function (arg) {
if(arg.data.count !== 0){
alert(sMobile+"手机号已被注册,请重新输入");
sReturnMobileValue = "";
}else{
alert(sMobile+"手机号能正常使用");
sReturnMobileValue = "success";
}
},
error:function () {
alert("手机号ajax,服务器超时,请重新输入");
sReturnMobileValue = "";
}
});
return sReturnMobileValue //返回出该信息
}
//短信验证
$smsCodeBtn.click(function(){
// 判定手机号是否有输入
if ( fn_check_mobile() !== "success"){
alert("手机号为空0");
return
}
// 判断用户是否输入图形验证码
let text = $smsCodeText.val();
if (!text){
alert("请输入图形验证码");
return
}
// 判断UUID
if(!sImageCodeId){
console.log("第2个"+sImageCodeId);
alert("图形UUID为空");
return
}
let dataParams={
'mobile':$mobile.val(),
'image_text':text,
"image_code_id":sImageCodeId,
};
$.ajax({
url:"/sms_code/",
type:"POST",
data:JSON.stringify(dataParams),
success:function(arg){
console.log(arg);
if(arg.errno==="200"){ // errno: "200", errmsg: "短信发送正常", data: null
alert("短信验证码发送成功");
//倒计时功能
let num = 60;
// 设置计时器
let t = setInterval(function () {
if (num===1){
clearInterval(t);
$smsCodeBtn.html("重新发送验证码")
}else{
num -= 1;
//展示倒计时信息
$smsCodeBtn.html(num+"秒");
}
},1000)
}else{
alert(arg.errmsg);
}
},
error:function(){
alert("短信验证ajax,服务器超时,请重试")
}
})
});
//注册
$register.submit(function(res){
//阻止默认提交操作
res.preventDefault();
//获取用户输入的内容
let sUsername = $username.val(); // 用户输入的用户名
let sPassword = $("input[name=password]").val(); //用户输入的密码
let sPasswordRepeat = $("input[name=password_repeat]").val(); //用户输入的确认密码
let sMobile = $mobile.val(); //用户输入的手机号码
let sSmsCode = $("input[name=sms_captcha]").val(); //短信验证码
//前端对前面5项进行判定
//判断用户名是否已被注册
if (fn_check_username() !=="success"){
//alert("用户已被注册,请重新输入");
return
}
//判断手机号是否已被注册
if(fn_check_mobile() !=="success"){
return
}
//判断密码或者确认密码是否为空
if((!sPassword) || (!sPasswordRepeat)){
alert("密码或者用户密码不能为空");
return
}
//判断密码和确认密码长度是否合适
if ((sPassword.length<6 || sPassword.length>20)||(sPasswordRepeat.length<6 || sPasswordRepeat.length>20)){
alert("密码长度不在6-20范围内");
return
}
//判断密码和确认密码是否一致
if(sPassword !== sPasswordRepeat){
alert("两次输入的密码不一致");
return
}
//判断短信验证码输入位数是否为6位
if(!(/^\d{6}$/).test(sSmsCode)){
alert("短信验证码长度不正确");
return
}
//发起注册
//1.注册参数
let sDataParams ={
"username": sUsername,
'mobile': sMobile,
'password': sPassword,
'password_repeat': sPasswordRepeat,
'sms_text': sSmsCode,
};
//创建ajax请求
$.ajax({
url:"/users/register/", //请求地址
type:"POST", //请求类型
data:JSON.stringify(sDataParams), //请求参数
contentType:"application/json;charset=utf-8", //请求数据类型前端发送给后端的
dataType:"json", //后端返回给前端的数据类型
success:function (arg) {
if(arg.errno==="200"){
alert("恭喜注册成功");
setTimeout(function(){
window.location.href = "/users/login/"; //注册成功后跳转到登录界面 document.referrer 回到上一个页面
},1500);
}else{
alert("注册失败:"+arg.errmsg)
}
},
error:function () {
alert("注册ajax,服务器超时,请重试")
}
})
});
// get cookie using jQuery
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
let cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
let cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
// Setting the token on the AJAX request
$.ajaxSetup({
beforeSend: function (xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
}
});
});