Django blog项目《七》:《注册功能2》提交注册

用户注册单个字段的功能已经实现,现在就是完成提交注册功能的实现。

提交注册功能和短信功能实现过程是一模一样的,只是字段验证多一些。

一、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'));
             }
        }
    });

});




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值