1 路由: from django.urls import path from . import views app_name = 'users' urlpatterns = [ path( 'checkpwd/', views.CheckPwd.as_view(), name='checkpwd'), path( 'logout/', views.LogoutView.as_view(), name='logout'), path('c_pwd/', views.C_pwd.as_view(), name='c_pwd'), ] 2 找回密码前端js,html略: $(()=> { let $img = $(".form-item .captcha-graph-img img"); // 获取图像 let $mobile = $('#mobile'); // 选择id为mobile的网页元素,需要定义一个id为mobile let sImageCodeId = ''; //默认为空 // 校验功能 // 定义一些状态变量 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; } let isMobileReady = false, send_flag = true; // 短信标记 genreate(); // 生成验证码 $img.click(genreate); // 点击触发新的 function genreate() { sImageCodeId = generateUUID(); let imageCodeUrl = '/image_code/' + sImageCodeId + '/'; // let imageCodeUrl = '/image_code/' + Math.floor(Math.random(5)); $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; } // 手机号验证逻辑 // 手机号校验,光标离开手机号输入框就校验 $mobile.blur(fn_check_mobile); function fn_check_mobile() { isMobileReady = false; let sMobile = $mobile.val(); // 获取用户输入的手机号码字符串 if (sMobile === "") { message.showError('手机号不能为空!'); return } if (!(/^1[345789]\d{9}$/).test(sMobile)) { message.showError('手机号码格式不正确,请重新输入!'); return } $.ajax({ url: '/mobile/' + sMobile + '/', type: 'GET', dataType: 'json', }) .done(function (res) { if (res.data.count < 1) { message.showError('未注册!'); } else { message.showSuccess('能正常使用!'); isMobileReady = true; } }) .fail(function () { message.showError('服务器超时,请重试!'); }); } // 发送短信验证码逻辑 let $smsCodeBtn = $('.form-item .sms-captcha'); // 获取短信验证码按钮元素,需要定义一个id为input_smscode let $imgCodeText = $('#input_captcha'); // 获取用户输入的图片验证码元素,需要定义一个id为input_captcha $smsCodeBtn.click(function () { // 判断手机号是否输入 if (send_flag) { send_flag = false; // 判断手机号码是否准备好 if (!isMobileReady) { fn_check_mobile(); return } // 判断用户是否输入图片验证码 let text = $imgCodeText.val(); // 获取用户输入的图片验证码文本 if (!text) { message.showError('请填写验证码!'); return } if (!sImageCodeId) { message.showError('图片UUID为空'); return } // 正常 let SdataParams = { 'mobile': $mobile.val(), // 获取用户输入的手机号 'text': text, // 获取用户输入的图片验证码文本 'image_code_id': sImageCodeId // 获取图片UUID }; $.ajax({ url: '/sms_code/', type: 'POST', headers: { "X-CSRFToken": getCookie("csrftoken") }, data: JSON.stringify(SdataParams), contentType: 'application/json; charset=utf-8', dataType: 'json', }) .done(function (res) { if (res.errno === "0") { // 倒计时60秒,60秒后允许用户再次点击发送短信验证码的按钮 message.showSuccess('短信验证码发送成功'); let num = 60; // 设置一个计时器 let t = setInterval(function () { if (num === 1) { // 如果计时器到最后, 清除计时器对象 clearInterval(t); // 将点击获取验证码的按钮展示的文本恢复成原始文本 $smsCodeBtn.html("获取验证码"); send_flag = true; } else { num -= 1; // 展示倒计时信息 $smsCodeBtn.html(num + "秒"); } }, 1000); } else { message.showError(res.errmsg); send_flag = true; } }) .fail(function () { message.showError('服务器超时,请重试!'); }); } }); let $register = $('.form-contain'); // 获取注册表单元素 $register.submit(function (e) { // 阻止默认提交操作 e.preventDefault(); let sPassword = $("input[name=password]").val(); let sMobile = $mobile.val(); // 获取用户输入的手机号码字符串 let sSmsCode = $("input[name=sms_captcha]").val(); // 判断手机号是否为空,是否已注册 if (!isMobileReady) { fn_check_mobile(); return } if (!(/^[0-9A-Za-z]{6,20}$/).test(sPassword)) { message.showError('请输入6到20位密码'); return } // 判断用户输入的短信验证码是否为6位数字 if (!(/^\d{6}$/).test(sSmsCode)) { message.showError('短信验证码格式不正确,必须为6位数字!'); return } // 发起注册请求 // 1、创建请求参数 let SdataParams = { "password": sPassword, "mobile": sMobile, "sms_code": sSmsCode }; // 2、创建ajax请求 $.ajax({ url: "/user/c_pwd/", // url尾部需要添加/ type: "POST", data: JSON.stringify(SdataParams), headers: { "X-CSRFToken": getCookie("csrftoken") }, contentType: "application/json; charset=utf-8", dataType: "json", }) .done(function (res) { if (res.errno === "0") { message.showSuccess('ok!'); setTimeout(() => { window.location.href = '/user/login/'; }, 1500) } else { message.showError(res.errmsg); } }) .fail(function () { message.showError('服务器超时,请重试!'); }); }); }) 3 views: from django.shortcuts import render from django.views import View from django.contrib.auth import login,logout from django.shortcuts import redirect,reverse from .models import Users from djang31pr.utils.res_code import res_json, Code, error_map from .forms import LoginForm from django.http import HttpResponseForbidden from django_redis import get_redis_connection import json,re #退出登录可以直接调用django内部方法清除session即可 class LogoutView(View): def get(self,request): logout(request) return redirect(reverse('users:index')) #修改密码 class CheckPwd(View): def get(self,request): return render(request,'user/check_pws.html') def post(self,request): mobile = request.POST.get('telephone') old = request.POST.get('old_password') new = request.POST.get('new_password') rep = request.POST.get('rep_password') cancel = request.POST.get('cancel') if cancel: return redirect(reverse('users:login')) if not all([mobile,old,new,rep]): return HttpResponseForbidden('用户名或密码不能为空!') if not re.match('^1[3-9]\d{9}$',mobile): return HttpResponseForbidden('请输入正确的手机号!') user = Users.objects.get(mobile=mobile) if user: try: user.check_password(old) except Exception as e: return HttpResponseForbidden('原始密码错误!') #新密码验证 if not re.match('^[0-9A-Za-z]{6,20}$',new): return HttpResponseForbidden('请输入6-20位字符的密码!') if new != rep: return HttpResponseForbidden('输入的新密码不一致!') if new==old: return HttpResponseForbidden('原始密码和新密码一样!') #密码修改 user.set_password(new) user.save() res = redirect(reverse('users:login')) return res else: return HttpResponseForbidden('用户不存在,请先注册!') class C_pwd(View): def get(self,request): title = '密码找回页面' return render(request,'user/c_pwd.html',context={'title':title}) def post(self,request): data = request.body if not data: return res_json(errno=Code.PARAMERR,errmsg=error_map[Code.PARAMERR]) data1 = json.loads(data) mobile = data1.get('mobile') sms_code = data1.get('sms_code') password = data1.get('password') if not re.match( '^1[3456789]\d{9}$', mobile ): return HttpResponseForbidden( '手机号错误' ) if Users.objects.filter( mobile=mobile ).count() < 1: return HttpResponseForbidden( '未注册!' ) # 1.读取redis中的短信验证码 redis_cli = get_redis_connection( 'verify_codes' ) sms_code_redis = redis_cli.get( 'sms_{}'.format( mobile ) ) # 2.判断是否过期 if sms_code_redis is None: return HttpResponseForbidden( '短信验证码已经过期' ) # 3.删除短信验证码,不可以使用第二次 redis_cli.delete( 'sms_' + mobile ) redis_cli.delete( 'send_flag_' + mobile ) # 4.判断是否正确,数据库的验证码需要解码 if sms_code_redis.decode() != sms_code: return HttpResponseForbidden('短信验证码错误!') if not password: return HttpResponseForbidden('密码不能为空!') if not re.match('^[0-9A-Za-z]{6,20}$', password): return HttpResponseForbidden('请输入6-20位字符的密码!') user = Users.objects.get(mobile=mobile) user.set_password(password) user.save() return res_json(errmsg='修改成功!')
其中容易出错的地方就是找路由 正则