五、用户名校验是否注册
1. 接口设计
1)接口说明

(?pgroup)这个格式的意思,在正则中是指给匹配到的group组名命名一个名称,且该名称是唯一的
例如:(?p\d{4}) 是匹配带有4个数字的,
(?p\w{4}) 是匹配带有4个字母的。
\w{5,20} 则代表我们输入的字母需要是5~20位数字的。
2)返回数据
返回结果为json数据:
{
"errno": 0 ,
"errmsg": "OK",
"data": {
"username":"username", # 查询用户名
"count": 1 # 用户查询数量
},
}
2. 后端代码
1)检查用户名是否注册的后端视图(first_project------>apps----->verivication----->view.py)


# 一、系统模块
import logging # 记录日志我们需要导入日志模块
# 二、django模块
from django.shortcuts import render # django渲染页面模块
from django.http import HttpResponse, JsonResponse # django的响应模块(本视图由于我们返回图片验证码需要使用它)
# 三、自己的库
from untils.captcha.captcha import captcha # 导入生成图形验证码的第三方模块
from . import constants # 导入我们创建的用来存放常量的py文件
from user.models import User # 导入我们写好的用户模型类
# 日志器
logger = logging.getLogger('django') # 生成一个名叫django的日志器
# 检查用户名是否注册(由于该方法只使用get访问,所以我们使用函数视图即可)
def check_username_view(request, username):
"""
username 用来获取路径参数username,所以该username需要与url中设置的username名称相同
函数功能:校验用户名
url: /username/(?P<username>\w{5,20})/
:param request:
:param username:
:return:
"""
# 到数据库查询数据并返回
data = {
"errno": 0,
"errmsg": "OK",
"data": {
"username": username , # 查询用户名
"count": User.objects.filter(username=username).count() # 用户查询数量
},
}
# 返回json数据
return JsonResponse(data)
2)url设置

3. 前端代码
1)前端用户名是否注册js验证
壹:首先导入一个写好的js文件,该文件用来提示各种信息


"use strict";
// 消息提示框
function Message() {
// 判断是否加载
this.isAppended = false;
// 提示框的宽度
this.wrapperWidth = 400;
// 提示框的高度
this.wrapperHeight = 48;
// 提示框初始化样式
this.initStyle();
// 提示框初始化元素
this.initElement();
// 提示框监听关闭按钮
this.listenCloseEvent();
}
// 初始化样式
Message.prototype.initStyle = function () {
// 错误消息文字和背景样式
this.errorStyle = {
"wrapper": {
"background": "#f8d7da",
"color": "#dc3545"
},
"close": {
"color": "#993d3d"
}
};
// 成功消息文字和背景样式
this.successStyle = {
"wrapper": {
"background": "#d4edda",
"color": "#28a745"
},
"close": {
"color": "#468847"
}
};
// 描述信息文字和背景样式
this.infoStyle = {
"wrapper": {
"background": "#d1ecf1",
"color": "#17a2b8"
},
"close": {
"color": "#5bc0de"
}
};
};
// 初始化元素
Message.prototype.initElement = function () {
// 设置提示框元素
this.wrapper = $("<div></div>");
// 设置提示框整体样式
this.wrapper.css({
'padding': '10px',
'font-size': '14px',
'width': this.wrapperWidth,
'position': 'fixed',
'z-index': 99999,
'left': 'calc(50% - ' + this.wrapperWidth / 2 + 'px)',
'top': -this.wrapperHeight,
'height': this.wrapperHeight,
'box-sizing': 'border-box',
'border': '1px solid #ddd',
'border-radius': '5px',
'line-height': 'calc(' + this.wrapperHeight / 2 + 'px)',
'font-weight': 600
});
// 生成关闭按钮
this.closeBtn = $("<span>×</span>");
// 关闭按钮的样式
this.closeBtn.css({
'float': 'right',
'cursor': 'pointer',
'font-size': '24px',
'font-weight': 500
});
// 提示文字的元素生成
this.messageSpan = $("<span class='py-message'></span>");
// 将提示文字的元素和关闭按钮添加到提示框中
this.wrapper.append(this.messageSpan);
this.wrapper.append(this.closeBtn);
};
// 关闭按钮的事件
Message.prototype.listenCloseEvent = function () {
var _this = this;
// 点击关闭
this.closeBtn.click(function () {
_this.wrapper.animate({ "top": -_this.wrapperHeight });
});
};
// 显示异常
Message.prototype.showError = function (message) {
this.show(message, "error");
};
Message.prototype.showSuccess = function (message) {
this.show(message, "success");
};
Message.prototype.showInfo = function (message) {
this.show(message, "info");
};
// 提示框的显示
Message.prototype.show = function (message, type) {
var _this2 = this;
// 如果没有添加 则添加
if (!this.isAppended) {
$(document.body).append(this.wrapper);
this.isAppended = true;
}
// 将各种提示的文字添加对应不同的样式
this.messageSpan.text(message);
if (type === "error") {
this.wrapper.css(this.errorStyle['wrapper']);
this.closeBtn.css(this.errorStyle['close']);
} else if (type === "info") {
this.wrapper.css(this.infoStyle['wrapper']);
this.closeBtn.css(this.infoStyle['close']);
} else if (type === "success") {
this.wrapper.css(this.successStyle['wrapper']);
this.closeBtn.css(this.successStyle['close']);
}
// 设置两秒后自动关闭
this.wrapper.animate({ "top": 0 }, function () {
setTimeout(function () {
_this2.wrapper.animate({ "top": -_this2.wrapperHeight });
}, 2500);
});
};
// 将对象绑定到 window 上
window.message = new Message();
该文件需要放在静态文件的js中的目录下:(文件路径:first_project--->static---->js----->base----->message.js)

贰:在register.js文件中写入验证用户是否注册的js(文件路径:first_project--->static---->js----->user----->register.js)


$(()=>{ //es6中的用法
// 1. 点击刷新我们的图片验证码
$('.captcha-graph-img img').click(function () {
// 重新加载一下图片验证码的src即可
$(this).attr('src','../verification/image_code/?rand=' + Math.random());
});
// 2. 校验功能
// 定义一些状态变量
let isUsernameReady = false, // 用户名是否准备好
isPasswordReady = false, // 密码是否准备好
isMobileReady = false, // 手机号是否准备好
isSmsCodeReady = false; // 短信验证码是否准备好
// 3. 用户名校验(光标离开用户名输入框就校验用户名)
let $form_msg = $('.form-control');
let $username = $form_msg.eq(0); //1. 获得用户名输入的对象
$username.blur(fnCheckUsername); //2. 当焦点离开用户名输入框时执行fnCheckUsername这个函数
function fnCheckUsername() { //3. 该函数用来校验用户名是否注册过,并响应结果给我们
// 默认未经校验的用户名为假,不通过校验
isUsernameReady = false;
// 获得我们输入的用户名
let sUsername = $username.val();
// 判断用户输入的用户名格式是否正确
if(sUsername === ""){
message.showError("用户名不能为空!");
}else if(!(/^\w{5,20}$/).test(sUsername)){
message.showError("请输入5-20个字符的用户名");
}else{
// 格式正确且不为空则发送ajax到后台(ajax是依赖于浏览器的一种技术)
$.ajax({
url: '../verification/username/'+ sUsername + '/',
type: 'GET',
dataType: 'json',
success: function (res) {
if(res.data.count!==0){
message.showError(res.data.username+"已经注册,请重新输入!");
}else{
isUsernameReady = True;
message.showInfo(res.data.username+"可以正常使用!");
}
},
error: function () {
message.showError("服务器超时,请重试!");
}
});
}
}
});
六、密码校验是否成功
1. 前端js代码(first_project--->static---->js----->user----->register.js)


$(()=>{ //es6中的用法
// 1. 点击刷新我们的图片验证码
$('.captcha-graph-img img').click(function () {
// 重新加载一下图片验证码的src即可
$(this).attr('src','../verification/image_code/?rand=' + Math.random());
});
// 2. 校验功能
// 定义一些状态变量
let isUsernameReady = false, // 用户名是否准备好
isPasswordReady = false, // 密码是否准备好
isMobileReady = false, // 手机号是否准备好
isSmsCodeReady = false; // 短信验证码是否准备好
// 3. 用户名校验(光标离开用户名输入框就校验用户名)
let $form_msg = $('.form-control');
let $username = $form_msg.eq(0); //1. 获得用户名输入的对象
$username.blur(fnCheckUsername); //2. 当焦点离开用户名输入框时执行fnCheckUsername这个函数
function fnCheckUsername() { //3. 该函数用来校验用户名是否注册过,并响应结果给我们
// 默认未经校验的用户名为假,不通过校验
isUsernameReady = false;
// 获得我们输入的用户名
let sUsername = $username.val();
// 判断用户输入的用户名格式是否正确
if(sUsername === ""){
message.showError("用户名不能为空!");
}else if(!(/^\w{5,20}$/).test(sUsername)){
message.showError("请输入5-20个字符的用户名");
}else{
// 格式正确且不为空则发送ajax到后台(ajax是依赖于浏览器的一种技术)
$.ajax({
url: '../verification/username/'+ sUsername + '/',
type: 'GET',
dataType: 'json',
success: function (res) {
if(res.data.count!==0){
message.showError(res.data.username+"已经注册,请重新输入!");
}else{
isUsernameReady = true;
message.showInfo(res.data.username+"可以正常使用!");
}
},
error: function () {
message.showError("服务器超时,请重试!");
}
});
}
}
// 4. 密码校验
// 获得用户输入的两次密码的对象
let $password1 = $form_msg.eq(1),
$password2 = $form_msg.eq(2);
// 当焦点离开第二次输入的密码框的时候触发函数
$password2.blur(fnCheckPassword);
// 该函数检查用户两次输入的密码是否一样
function fnCheckPassword() {
if($password1.val() === ""){
message.showError("密码不能为空");
}else if($password1.val() !== $password2.val()){
message.showError("两次密码输入不一致,请重新输入");
}else{
isPasswordReady = true;
message.showInfo("密码可以正常使用!");
}
}
});
七、电话号码校验
1. 接口设计
1)接口说明

2)返回数据
返回结果为json数据:
{
"errno": 0 ,
"errmsg": "OK",
"data": {
"mobile":"mobile", # 查询手机号码
"count": 1 # 手机号查询数量
},
}
2. 后端代码
1)检查手机号是否注册的视图(first_project------>apps----->verivication----->view.py)


# 一、系统模块
import logging # 记录日志我们需要导入日志模块
# 二、django模块
from django.shortcuts import render # django渲染页面模块
from django.http import HttpResponse, JsonResponse # django的响应模块(本视图由于我们返回图片验证码需要使用它)
# 三、自己的库
from untils.captcha.captcha import captcha # 导入生成图形验证码的第三方模块
from . import constants # 导入我们创建的用来存放常量的py文件
from user.models import User # 导入我们写好的用户模型类
# 日志器
logger = logging.getLogger('django') # 生成一个名叫django的日志器
# 1.生成图形验证码
def image_code_view(request):
"""
功能:生成验证码
url : /image_code/
:param request:
:return:
"""
# 1. 生成验证码(随机生成字符和图片)
text, image = captcha.generate_captcha() # 调用该方法会给我们返回两个值,一个是验证码的文字内容,一个是验证码的图片
# 2. 在后端保存验证码(为了之后校验验证码是否正确,所以现在我们需要保存验证码)
request.session['image_code'] = text # 将验证码文字部分存放在session中
# 给验证码一个过期时间,为了方便日后修改,我们在校验app中创建一个constants.py的文件,用来存放常量
# 导入方式为 from . import constants
request.session.set_expiry(constants.IMAGE_CODE_EXPIRES) # 设置session过期时间
# 3. 记录一个日志
logger.info('Image_code:{}'.format(text))
# 4. 返回验证码图片
# image存储的是图片的二进制数据,content指定了返回的数据内容,
# content_type指定了返回数据的类型,告诉浏览器我们返回的是一张图片
return HttpResponse(content=image, content_type='image/jpg')
# 2.检查用户名是否注册(由于该方法只使用get访问,所以我们使用函数视图即可)
def check_username_view(request, username):
"""
username 用来获取路径参数username,所以该username需要与url中设置的username名称相同
函数功能:校验用户名
url: /username/(?P<username>\w{5,20})/
:param request:
:param username:
:return:
"""
# 到数据库查询数据并返回
data = {
"errno": 0,
"errmsg": "OK",
"data": {
"username": username , # 查询用户名
"count": User.objects.filter(username=username).count() # 用户查询数量
},
}
# 返回json数据
return JsonResponse(data)
# 3.检查手机号码是否注册(由于该方法只使用get访问,所以我们使用函数视图即可)
def check_mobile_view(request, mobile):
"""
函数功能:校验手机号码
url: /mobile/(?P<mobile>1[3-9]\d{9})/
:param request:
:param username:
:return:
"""
# 到数据库查询数据并返回
data = {
"errno": 0,
"errmsg": "OK",
"data": {
"mobile": mobile , # 查询手机号码
"count": User.objects.filter(mobile=mobile).count() # 手机号码查询数量
},
}
# 返回json数据
return JsonResponse(data)
2) 设置该视图的路由


from django.urls import path,re_path
from . import views
urlpatterns = [
path('image_code/', views.image_code_view, name='image_code'), # 图形验证码路由
re_path('username/(?P<username>\w{5,20})/',views.check_username_view, name='check_username'), # 检查用户名是否注册路由
re_path('mobile/(?P<mobile>1[3-9]\d{9})/',views.check_mobile_view, name='check_mobile'), # 检查手机号码是否注册路由
]
3. 前端代码(文件路径:first_project--->static---->js----->user----->register.js)


$(()=>{ //es6中的用法
// 1. 点击刷新我们的图片验证码
$('.captcha-graph-img img').click(function () {
// 重新加载一下图片验证码的src即可
$(this).attr('src','../verification/image_code/?rand=' + Math.random());
});
// 2. 校验功能
// 定义一些状态变量
let isUsernameReady = false, // 用户名是否准备好
isPasswordReady = false, // 密码是否准备好
isMobileReady = false, // 手机号是否准备好
isSmsCodeReady = false; // 短信验证码是否准备好
// 3. 用户名校验(光标离开用户名输入框就校验用户名)
let $form_msg = $('.form-control'); // 获得表单对象
let $username = $form_msg.eq(0); //1. 获得表单中的第一个,用户名输入框的对象
$username.blur(fnCheckUsername); //2. 当焦点离开用户名输入框时执行fnCheckUsername这个函数
function fnCheckUsername() { //3. 该函数用来校验用户名是否注册过,并响应结果给我们
isUsernameReady = false; // 默认未经校验的用户名为假,不通过校验
let sUsername = $username.val(); // 获得我们输入的用户名
if(sUsername === ""){ // 判断用户输入的用户名格式是否正确
message.showError("用户名不能为空!");
}else if(!(/^\w{5,20}$/).test(sUsername)){
message.showError("请输入5-20个字符的用户名");
}else{
$.ajax({ // 格式正确且不为空则发送ajax到后台(ajax是依赖于浏览器的一种技术)
url: '../verification/username/'+ sUsername + '/',
type: 'GET',
dataType: 'json',
success: function (res) {
if(res.data.count!==0){
message.showError(res.data.username+"已经注册,请重新输入!");
}else{
isUsernameReady = true;
message.showInfo(res.data.username+"可以正常使用!");
}
},
error: function () {
message.showError("服务器超时,请重试!");
}
});
}
}
// 4. 密码校验
// 获得用户输入的两次密码的对象
let $password1 = $form_msg.eq(1),
$password2 = $form_msg.eq(2);
// 当焦点离开第二次输入的密码框的时候触发函数
$password2.blur(fnCheckPassword);
// 该函数检查用户两次输入的密码是否一样
function fnCheckPassword() {
isPasswordReady = false; // 默认密码错误
if($password1.val() === ""){
message.showError("密码不能为空");
}else if($password1.val() !== $password2.val()){
message.showError("两次密码输入不一致,请重新输入");
}else{
isPasswordReady = true; // 校验成功后我们设置密码正确
message.showInfo("密码可以正常使用!");
}
}
// 5. 手机号码校验
// 获得用户手机号输入框对象
let $mobile = $form_msg.eq(3); // 1. 获得表单中的第四个,手机号码输入框的对象
$mobile.blur(fnCheckMobile); // 2. 当焦点离开手机号输入框时触发函数
function fnCheckMobile() { // 3. 该函数校验手机号码是否正确
isMobileReady = false; // 3.1 默认手机号输入错误
let sMobile = $mobile.val(); // 3.2 获得用户输入的手机号
if(sMobile === ""){
message.showError("手机号不能为空");
}else if(!(/^1[3-9]\d{9}$/).test(sMobile)){
message.showError("手机号格式不正确");
}else{
$ // 3.3 发送ajax(新的方式写ajax)
.ajax({ // 3.3.1.发送的ajax信息
url: '../verification/mobile/'+ sMobile + '/',
type: 'GET',
dataType: 'json',
})
.done((res)=>{ // 3.3.2. 返回成功执行ajax信息,相当于success
if(res.data.count!==0){
message.showError(res.data.mobile+"已经注册,请重新输入!");
}else{
isMobileReady = true; // 3.3.3 符合校验条件设置手机正确
message.showInfo(res.data.mobile+"可以正常使用!");
}
})
.fail(()=>{ // 3.3.4. 返回失败执行ajax信息,相当于error
message.showError("服务器超时!");
})
}
}
});
八、Json响应结构设计
1. 目的
1)减少代码冗余,提高复用性,还可以解耦
2)便于分工协作
2. 结构设计
1)结构代码
data = {
"errno": 0,
"errmsg": "OK",
"data": {...},
}
2)参数说明

3)错误信息和错误编码的集合类(为了统一方便管理,一般会由你的项目总监发给你)
(该集合类的文件位置为:first_project----->untils---->res_code.py , 注意res_code这个名字可随意起)


class Code:
OK = "0"
DBERR = "4001"
NODATA = "4002"
DATAEXIST = "4003"
DATAERR = "4004"
METHERR = "4005"
SMSERROR = "4006"
SMSFAIL = "4007"
SESSIONERR = "4101"
LOGINERR = "4102"
PARAMERR = "4103"
USERERR = "4104"
ROLEERR = "4105"
PWDERR = "4106"
SERVERERR = "4500"
UNKOWNERR = "4501"
error_map = {
Code.OK: "成功",
Code.DBERR: "数据库查询错误",
Code.NODATA: "无数据",
Code.DATAEXIST: "数据已存在",
Code.DATAERR: "数据错误",
Code.METHERR: "方法错误",
Code.SMSERROR: "发送短信验证码异常",
Code.SMSFAIL: "发送短信验证码失败",
Code.SESSIONERR: "用户未登录",
Code.LOGINERR: "用户登录失败",
Code.PARAMERR: "参数错误",
Code.USERERR: "用户不存在或未激活",
Code.ROLEERR: "用户身份错误",
Code.PWDERR: "密码错误",
Code.SERVERERR: "内部错误",
Code.UNKOWNERR: "未知错误",
}
3. 函数设计(由于我们一个项目中可能会发送很多个json,为了减少代码冗余,我们设计一个函数,为了方便调用我们就将该函数同样的写照res_code.py这个文件中了)


from django.http import JsonResponse
# 错误编码集合
class Code:
OK = "0"
DBERR = "4001"
NODATA = "4002"
DATAEXIST = "4003"
DATAERR = "4004"
METHERR = "4005"
SMSERROR = "4006"
SMSFAIL = "4007"
SESSIONERR = "4101"
LOGINERR = "4102"
PARAMERR = "4103"
USERERR = "4104"
ROLEERR = "4105"
PWDERR = "4106"
SERVERERR = "4500"
UNKOWNERR = "4501"
# 错误编码对应的错误信息集合
error_map = {
Code.OK: "成功",
Code.DBERR: "数据库查询错误",
Code.NODATA: "无数据",
Code.DATAEXIST: "数据已存在",
Code.DATAERR: "数据错误",
Code.METHERR: "方法错误",
Code.SMSERROR: "发送短信验证码异常",
Code.SMSFAIL: "发送短信验证码失败",
Code.SESSIONERR: "用户未登录",
Code.LOGINERR: "用户登录失败",
Code.PARAMERR: "参数错误",
Code.USERERR: "用户不存在或未激活",
Code.ROLEERR: "用户身份错误",
Code.PWDERR: "密码错误",
Code.SERVERERR: "内部错误",
Code.UNKOWNERR: "未知错误",
}
# json结构化函数(之后我们凡事需要返回json数据的时候均调用这个快捷方法)
def json_response(error=Code.OK, errmsg='', data=None, kwargs=None):
json_dict = {
'error': error,
'errmg': errmsg,
'data' : data
}
if kwargs and isinstance(kwargs, dict) : # 判断kwargs是否不为空,且它是否是个字典
json_dict.update(kwargs) # 如果是,则将kwargs扩展添加到json_dict这个字典中
return JsonResponse(json_dict) # 返回我们获得的字典
4. 修改我们之前返回的json数据函数(调用我们的快捷方式来返回,文件位置:first_project------>apps----->verivication----->view.py)




文件位置:


# 一、系统模块
import logging # 记录日志我们需要导入日志模块
# 二、django模块
from django.shortcuts import render # django渲染页面模块
from django.http import HttpResponse, JsonResponse # django的响应模块(本视图由于我们返回图片验证码需要使用它)
# 三、自己的库
from untils.captcha.captcha import captcha # 导入生成图形验证码的第三方模块
from . import constants # 导入我们创建的用来存放常量的py文件
from user.models import User # 导入我们写好的用户模型类
from untils.res_code import json_response # 导入我们写好的json快捷函数
# 日志器
logger = logging.getLogger('django') # 生成一个名叫django的日志器
# 1.生成图形验证码
def image_code_view(request):
"""
功能:生成验证码
url : /image_code/
:param request:
:return:
"""
# 1. 生成验证码(随机生成字符和图片)
text, image = captcha.generate_captcha() # 调用该方法会给我们返回两个值,一个是验证码的文字内容,一个是验证码的图片
# 2. 在后端保存验证码(为了之后校验验证码是否正确,所以现在我们需要保存验证码)
request.session['image_code'] = text # 将验证码文字部分存放在session中
# 给验证码一个过期时间,为了方便日后修改,我们在校验app中创建一个constants.py的文件,用来存放常量
# 导入方式为 from . import constants
request.session.set_expiry(constants.IMAGE_CODE_EXPIRES) # 设置session过期时间
# 3. 记录一个日志
logger.info('Image_code:{}'.format(text))
# 4. 返回验证码图片
# image存储的是图片的二进制数据,content指定了返回的数据内容,
# content_type指定了返回数据的类型,告诉浏览器我们返回的是一张图片
return HttpResponse(content=image, content_type='image/jpg')
# 2.检查用户名是否注册(由于该方法只使用get访问,所以我们使用函数视图即可)
def check_username_view(request, username):
"""
username 用来获取路径参数username,所以该username需要与url中设置的username名称相同
函数功能:校验用户名
url: /username/(?P<username>\w{5,20})/
:param request:
:param username:
:return:
"""
# # 到数据库查询数据并返回
# data = {
# "errno": 0,
# "errmsg": "OK",
# "data": {
# "username": username , # 查询用户名
# "count": User.objects.filter(username=username).count() # 用户查询数量
# },
# }
# # 返回json数据
# return JsonResponse(data)
data = {
"username": username , # 查询用户名
"count": User.objects.filter(username=username).count() # 用户查询数量
}
# 返回json数据
return json_response(data=data)
# 3.检查手机号码是否注册(由于该方法只使用get访问,所以我们使用函数视图即可)
def check_mobile_view(request, mobile):
"""
函数功能:校验手机号码
url: /mobile/(?P<mobile>1[3-9]\d{9})/
:param request:
:param username:
:return:
"""
# # 到数据库查询数据并返回
# data = {
# "errno": 0,
# "errmsg": "OK",
# "data": {
# "mobile": mobile , # 查询手机号码
# "count": User.objects.filter(mobile=mobile).count() # 手机号码查询数量
# },
# }
# # 返回json数据
# return JsonResponse(data)
# 到数据库查询数据并返回
data = {
"mobile": mobile, # 查询手机号码
"count": User.objects.filter(mobile=mobile).count() # 手机号码查询数量
}
# 返回json数据
return json_response(data=data)
来源:https://www.cnblogs.com/wangyusu/p/11342860.html
