1.分析
请求方法:GET
url定义:/mobiles/(?P<mobile>1[3-9]\d{9})/
请求参数:url路径参数
参数 | 类型 | 前端是否必须传 | 描述 |
---|---|---|---|
mobile | 字符串 | 是 | 用户输入的手机号 |
# 在verifications目录下的views.py文件中定义如下类视图:
class MobileView(View):
"""
判断手机号是否存在
"""
def get(self, request, username):
data = {
'mobile': mobile,
'count': Users.objects.filter(mobile=mobile).count()
}
return to_json_data(data=data)
在 urls 文件中:进行路由匹配:
re_path('mobiles/(?P<mobile>1[3-9]\d{9})/', views.CheckMobileView.as_view(), name='check_mobiles'),
前台代码代码:js 文件:
$(function () {
let $username = $('#user_name'); // 选择id为user_name的网页元素,需要定义一个id为user_name
let $img = $(".form-item .captcha-graph-img img"); // 获取图像标签
let sImageCodeId = ""; // 定义图像验证码ID值
let $mobile = $('#mobile'); // 选择id为mobile的网页元素,需要定义一个id为mobile
// 1、图像验证码逻辑
generateImageCode(); // 生成图像验证码图片
$img.click(generateImageCode); // 点击图片验证码生成新的图片验证码图片
// 判断用户是否注册
// 2、用户名验证逻辑
$username.blur(function () {
fn_check_usrname();
});
// 3、手机号验证逻辑
// 判断用户手机号是否注册
$mobile.blur(function () {
fn_check_mobile();
});
// 生成一个图片验证码的编号,并设置页面中图片验证码img标签的src属性
function generateImageCode() {
// 1、生成一个图片验证码随机编号
sImageCodeId = generateUUID();
// 2、拼接请求url /image_codes/<uuid:image_code_id>/
let imageCodeUrl = "/image_codes/" + sImageCodeId + "/";
// 3、修改验证码图片src地址
$img.attr('src', imageCodeUrl)
}
// 生成图片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 fn_check_usrname() {
let sUsername = $username.val(); // 获取用户名字符串
if (sUsername === "") {
message.showError('用户名不能为空!');
return
}
// test()方法 判断字符串中是否匹配到正则表达式内容,返回的是boolean值 ( true / false )
if (!(/^\w{5,20}$/).test(sUsername)) {
message.showError('请输入5-20个字符的用户名');
return
}
// 发送ajax请求,去后端查询用户名是否存在
$.ajax({
url: '/usernames/' + sUsername + '/',
type: 'GET',
dataType: 'json',
// data:{'code':300268}
})
.done(function (res) {
if (res.data.count !== 0) {
message.showError(res.data.username + '已注册,请重新输入!')
} else {
message.showInfo(res.data.username + '能正常使用!')
}
})
.fail(function () {
message.showError('服务器超时,请重试!');
});
}
function fn_check_mobile() {
let sMobile = $mobile.val(); // 获取用户输入的手机号码字符串
let SreturnValue = "";
if (sMobile === "") {
message.showError('手机号不能为空!');
return
}
if (!(/^1[345789]\d{9}$/).test(sMobile)) {
message.showError('手机号码格式不正确,请重新输入!');
return
}
$.ajax({
url: '/mobiles/' + sMobile + '/',
type: 'GET',
dataType: 'json',
async: false // 把async关掉
})
.done(function (res) {
if (res.data.count !== 0) {
message.showError(res.data.mobile + '已注册,请重新输入!')
SreturnValue = ""
} else {
SreturnValue = "success"
}
})
.fail(function () {
message.showError('服务器超时,请重试!');
SreturnValue = ""
});
return SreturnValue
}
});
发送手机短信验证码功能实现
1.分析
业务处理流程:
-
检查图片验证码是否正确
-
检查是否在60s内有发送记录
-
生成短信验证码
-
保存短信验证码与发送记录
-
发送短信
请求方法:POST
url定义:/sms_codes
请求参数:url路径参数
参数 | 类型 | 前端是否必须传 | 描述 |
---|---|---|---|
mobile | 字符串 | 是 | 用户输入的手机号 |
image_code_id | UUID | 是 | js生成的图片uuid号 |
text | 字符串 | 是 | 用户输入的图片验证码文本 |
注:由于是post请求,在向后端发起请求时,需要附带csrf token
1,创建个类,
2,获取前台参数,
3,校验参数,
4,发送短信验证码,
5,保存短信验证码
6,返回前台参数
在verifications目录下的forms.py文件中定义如下form表单:
# 创建手机号的正则校验器
from django import forms
from django.core.validators import RegexValidator
from django_redis import get_redis_connection
from users.models import Users
mobile_validator = RegexValidator(r"^1[3-9]\d{9}$", "手机号码格式不正确")
a
class CheckImgCodeForm(forms.Form):
"""
check image code
"""
mobile = forms.CharField(max_length=11, min_length=11, validators=[mobile_validator, ],
# 错误提示信息
error_messages={"min_length": "手机号长度有误", "max_length": "手机号长度有误",
"required": "手机号不能为空"})
image_code_id = forms.UUIDField(error_messages={"required": "图片UUID不能为空"})
text = forms.CharField(max_length=4, min_length=4,
error_messages={"min_length": "图片验证码长度有误", "max_length": "图片验证码长度有误",
"required": "图片验证码不能为空"})
# Cleaning and validating fields that depend on each other
def clean(self):
cleaned_data = super().clean()
# 1、
image_uuid = cleaned_data.get("image_code_id")
image_text = cleaned_data.get("text")
mobile_num = cleaned_data.get("mobile")
# 2、
if Users.objects.filter(mobile=mobile_num).count():
raise forms.ValidationError("手机号已注册,请重新输入")
# 确保settings.py文件中有配置redis CACHE
# Redis原生指令参考 http://redisdoc.com/index.html
# Redis python客户端 方法参考 http://redis-py.readthedocs.io/en/latest/#indices-and-tables
# 2、
con_redis = get_redis_connection(alias='verify_codes')
# 创建保存到redis中图片验证码的key
img_key = "img_{}".format(image_uuid).encode('utf-8')
# 取出图片验证码
real_image_code_origin = con_redis.get(img_key)
real_image_code = real_image_code_origin.decode('utf-8') if real_image_code_origin else None
con_redis.delete(img_key)
# 验证手机号
if (not real_image_code) or (image_text != real_image_code):
raise forms.ValidationError("图片验证失败")
# 检查是否在60s内有发送记录
sms_flag_fmt = "sms_flag_{}".format(mobile_num).encode('utf-8')
sms_flag = con_redis.get(sms_flag_fmt)
if sms_flag:
raise forms.ValidationError("获取手机短信验证码过于频繁")