Django博客搭建_找回密码

Blog项目——找回密码

一、 分析

业务处理流程:

  • 判断手机号是否为空,是否已注册
  • 判断短信验证码是否为空,是否格式正确,是否与真实的短信验证码相同
  • 判断密码是否为空,格式是否正确
  • 判断确认密码与密码是否相同

请求方法POST

url定义/user/findpwd/

请求参数:url路径参数

参数类型前端是否必须传描述
password字符串用户输入的密码
password_repeat字符串用户输入的重复密码
mobile字符串用户输入的手机号
sms_code字符串用户输入的短信验证码

注:由于是post请求,在向后端发起请求时,需要附带csrf token

二、步骤

  1. 用户输入手机号(js判断是否为空,是否注册)
  2. 用户输入图形验证码
  3. 点击发送短信验证码(查看手机是否合法,验证码是否合法)
  4. 获取验证码,输入密码与重复密码,点击修改密码
  5. 获取每个值
  6. 判断每个值是否为空,是否合法
  7. 通过ajax往后台传json数据
  8. 后台接收数据
    1. 判断是否为空
    2. 将数据放入form表单进行数据清洗
    3. 如果数据正确,则将密码修改
    4. 如果不正确则返回错误信息
  9. 前台获取后台传来的响应码
    1. 如果是0,则重定向到登陆页面
    2. 如果不是0,则显示错误原因

三、代码

1. 前端

前端的代码与之前用户注册差不多,函数部分也是用到了类似的几个(拼接图片url,uuid,检查miobile是否注册,发送短信和修改密码)

接下来就来看看:

// @Auther:Summer
$(function () {
    let $img = $(".form-item .captcha-graph-img img"); // get img
    let $mobile = $("#mobile");
    let $smsCodeBtn = $(".form-item .sms-captcha"); //get sms btn
    let $mobileRetuenVal = ""; // this is run mobile_fun return val
    let $findPwsBtn = $(".findpsw-btn");

    generate();
    $img.click(generate);

    $mobile.blur(function () {
        $mobileRetuenVal = fn_check_mobile();
    })

    // set make img fun
    function generate() {
        imageUUID = generateUUID();
        let imageUrl = "/image_code/" + imageUUID +"/";
        $img.attr("src", imageUrl)
    }

    // the fun to create uuid_code
    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;
    }

    // to check mobile whether register
    function fn_check_mobile() {
        let sRetuenVal = "";
        let sMobile = $mobile.val();  // get mobile val

        // check mobile whether null
        if(sMobile === ""){
            message.showError("手机号不能为空");
            return sRetuenVal;
        }

        // use re to check mobile
        if (!(/^1[3-9]\d{9}$/).test(sMobile)){
            message.showError("手机号格式错误,请重新输入");
            return sRetuenVal;
        }

        // send ajax
        $.ajax({
            url: "/mobiles/" + sMobile + "/",
            type: "GET",
            dataType: "json",
            async: false
        }).done(function (res) {
            if(res.data.count !== 1){
                message.showError("输入的手机号有误,请重新输入");
            }else{
                message.showSuccess("手机号输入正确");
                sRetuenVal = "success";
            }
        }).fail(function () {
            message.showError("服务器超时,请重试");
        })
        return sRetuenVal;
    }

    // send sms
    $smsCodeBtn.click(function () {
        // check moile
        if($mobileRetuenVal !== "success"){
            message.showError("请输入正确的手机号");
            return;
        }

        // get val
        let text = $("#input_captcha").val();

        // check code
        if(!text){
            message.showError("请输入验证码");
            return;
        }

        // check uuid of img
        if(!imageUUID){
            message.showError("图片uuid码为空");
            return;
        }

        // set data
        let sDataParm = {
            "mobile": $mobile.val(),
            "text": text,
            "image_code_id": imageUUID
        }

        // send ajax
        $.ajax({
            url: "/sms_code/",
            type: "POST",
            data: JSON.stringify(sDataParm),
            dataType: "json"
        }).done(function (res) {
            if(res.errno === "0"){
                message.showSuccess("短信验证码发送成功")
                $smsCodeBtn.attr('disabled',true);
                let num = 60;
                let t = setInterval(function () {
                    if(num === 1){
                        // 如果计时器到最后, 清除计时器对象
                        clearInterval(t);
                        $smsCodeBtn.attr('disabled',false);
                        // 将点击获取验证码的按钮展示的文本恢复成原始文本
                        $smsCodeBtn.html("重新发送验证码");
                    }else {
                        num -= 1;
                        $smsCodeBtn.html(num + "秒");
                    }
                },1000
            )}else{
                message.showError(res.errmsg);
        }}).fail(
            message.showError("服务器超时,请重试")
        )
    })

    // change psw
    $findPwsBtn.click(function (e) {
        // prevent default submit
        e.preventDefault();

        // get all 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();

        // check moile
        if($mobileRetuenVal !== "success"){
            message.showError("请输入正确的手机号");
            return;
        }

        // check password
        if((!sPassword) || (!sPasswordRepeat)){
            message.showError("密码与确认密码不能为空")
            return;
        }

        // check passwd len
        if((sPassword.length < 6 || sPassword.length > 20) ||
            (sPasswordRepeat.length < 6 || sPasswordRepeat.length > 20)){
            message.showError("密码和确认密码的长度需在6-20位")
            return;
        }

        // check pass and pass_re whether same
        if(sPassword !== sPasswordRepeat){
            message.showError("密码和确认密码不一致")
            return;
        }

        // check smscode len
        if(!(/^\d{6}$/).test(sSmsCode)){
            message.showError("短信验证码格式不正确,必须是6位数字!")
            return;
        }

        // request
        // set request data
        let SdataParams = {
            "password": sPassword,
            "password_repeat": sPasswordRepeat,
            "mobile": sMobile,
            "sms_code": sSmsCode
        };

        // send ajax
        $.ajax({
            url: "/user/findpwd/",
            type:"POST",
            data: JSON.stringify(SdataParams),
            // 请求内容的数据类型(前端发给后端的格式)
            contentType: "application/json; charset=utf-8",
            dataType: "json",
        }).done(function (res) {
            if(res.errno === "0"){
                message.showSuccess("修改密码成功");
                setTimeout(() =>{
                    // redirect to login page
                    window.location.href = '/user/login/';
                },1500)
            }else{
                message.showError(res.errmsg);
            }
        }).fail(function () {
            message.showError("服务器超时,请重试")
        })
    })
});

注意,上面的代码原来是

$findPwsBtn.submit(function (e) {
        // prevent default submit
        e.preventDefault();

这里变成了click,应为尝试了无数次,始终无法解开:

当使用submit的时候,无法接触默认操作,而只有在click的时候才能执行这个操作。如果有知道为什么会出现这样错误的,也欢迎留言区留下宝贵意见。

2. 后端——form

form用来进行数据清洗,主要的代码也与上次的form类似:

class ChangePswForm(forms.Form):
    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,
                               error_messages={
                                   "max_length": "手机号长度有误",
                                   "min_length": "手机号长度有无",
                                   "required": "手机号不能为空"})
    sms_code = forms.CharField(label="验证码", max_length=6, min_length=6,
                               error_messages={"max_length": "验证码长度有误",
                                               "min_length": "验证码长度有误",
                                               "required": "验证码不能为空"})

    # 检查手机号是否存在
    def clean_mobile(self):
        tel = self.cleaned_data.get('mobile')
        if not Users.objects.filter(mobile=tel).exists():
            raise forms.ValidationError("手机号输入有误,请重新输入!")
        return tel

    def clean(self):
        cleaned_data = super().clean()
        passwd = cleaned_data.get('password')
        passwd_repeat = cleaned_data.get('password_repeat')

        if passwd != passwd_repeat:
            raise forms.ValidationError("两次密码不一致")

        # 校验短信验证码
        tel = cleaned_data.get('mobile')
        sms_text = cleaned_data.get('sms_code')

        # 建立redis连接
        redis_conn = get_redis_connection(alias='verify_codes')
        sms_fmt = "sms_{}".format(tel).encode('utf8')
        real_sms = redis_conn.get(sms_fmt)
        if (not real_sms) or (sms_text != real_sms.decode('utf-8')):
            raise forms.ValidationError("短信验证码错误")

3. 后端——view

view里需要注意的一个点就是,如果直接获取user实例,然后通过user.password=password是无法进行加密处理的,这里我使用了AbstractUser类自带的set_password函数

class FindPswView(View):
	def get(self, request):
		return render(request, 'users/findpsw.html')

	def post(self, request):
		json_data = request.body
		if not json_data:
			return to_json_data(errno=Code.PARAMERR, errmsg=[error_map[Code.PARAMERR]])
		data_dict = json.loads(json_data.decode("utf8"))
		form = ChangePswForm(data=data_dict)
		if form.is_valid():
			mobile = form.cleaned_data.get("mobile")
			password = form.cleaned_data.get("password")
			user = Users.objects.get(mobile=mobile)
			user.set_password(password)
			user.save()
			return to_json_data(errmsg="密码修改成功")

		else:
			error_map_list = []
			for item in form.errors.values():
				error_map_list.append(item)
			err_str = "/".join(error_map_list)
			return to_json_data(errno=Code.PARAMERR, errmsg=err_str)

更加别忘了,要保存!!!

4. url

# -*- coding: utf-8 -*-
# @Author  : summer
from django.urls import path
from . import views

app_name = "user"

urlpatterns = [
	path("login/", views.LoginView.as_view(), name="login"),
	path("register/", views.RegistarView.as_view(), name="register"),
	path("findpwd/", views.FindPswView.as_view(), name="findpwd"),
]
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值