利用django form组件+ajax实现用户认证

首先定义一个表单类(继承forms.Form):

登录后复制

from django import forms
from django.core import validators
from django.forms import CharField
from cdnpanel.models import User
from django.core.exceptions import ValidationError

mobile_validator = validators.RegexValidator(r"^1[3-9]\d{9}$", "手机号码格式不正确")

class regform(forms.Form):
    username = forms.CharField(
        max_length=8,
        min_length=2,
        required=True,
        error_messages={"max_length": "最大长度不能超过8", "min_length": "最小长度不能小于2", "required": "用户名不能为空"},
    )
    password = forms.CharField(
        min_length=8,
        required=True,
        error_messages={"min_length": "最小长度不能小于8", "required": "密码不能为空"},
    )
    email = forms.EmailField(error_messages={"required": "邮箱不能为空"})
    name = forms.CharField(max_length=8, required=False)
    tel = forms.CharField(max_length=11, min_length=11, validators=[mobile_validator, ],
                          error_messages={"min_length": "手机号长度有误", "max_length": "手机号长度有误",
                                          "required": "手机号不能为空"})
    gender = forms.ChoiceField(
        choices=(('male', "女"), ("female", "女")),
        error_messages={"required": "性别不能为空"})
    birthday = forms.DateField(
        error_messages={"required": "生日不能为空"}
    )

    # 自定义验证,格式:clean_列名
    # 这是局部验证,因为不确定其他参数是否放在cleaned_data里面

    def clean_username(self):
        username = self.cleaned_data.get("username")
        if User.objects.filter(username=username).exists():
            raise ValidationError("用户已存在")
        else:
            return username

    # 全局验证,以上的步骤都执行完,最后执行此函数
    def clean(self):
        pass

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.

这里把里面的属性值设置为跟前端post请求中的参数值一样,这样当实例化form类的时候只要把post请求传递进去:

data = regform(data=request.POST)

form类的字段格式简单易懂:

登录后复制

 要检测字段名=forms.字段类型(各种检测参数)

检测参数比较常用的有:

max_length:最大长度

min_length:最小长度

error_messages:自定义错误信息,格式:检测名+自定义的错误信息

widget:html插件

form组件主要功能就是自定义的正则匹配(做验证用)+html插件功能(前端展示)

如果form组件自带的检测参数不足以满足需求,form组件还允许自定义函数:

局部检测:clean_字段名(比如定义了age,想再检测age,就在form类里面定义,clean_age()函数,若返回错误,可以raise对应错误类型,默认只能捕捉ValidationError,若正确,返回age即可)

全局检测函数:clean()函数

form类在实例并不检测,只有在执行is_valid()方法时才开始检测,检测顺序就是: form的规则–>clean_局部函数–>clean函数

view部分:

登录后复制

from django.core.exceptions import ValidationError
from django.db import IntegrityError
from django.shortcuts import redirect, render, HttpResponse
from cdnpanel.models import User, Domain, Proxy
from cdnpanel.pager import Pagination
from cdnpanel.def_form import regform
def register(request):
    if request.method == "GET":
        return render(request, 'register.html')
    else:
        if request.is_ajax():
            data = regform(data=request.POST)
            ajax_rsp = {"status": "err", "msg": None}
            if data.is_valid():
                ajax_rsp["status"] = "ok"
                User.objects.create(**data.cleaned_data)
            else:
                ajax_rsp['status'] = "err"
                ajax_rsp["msg"] = data.errors
        return HttpResponse(json.dumps(ajax_rsp))
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.

regester.html部分

登录后复制


<!DOCTYPE html>
<html >
<head>
    <meta charset="UTF-8">
    <title>注册页面</title>
    <!--    引入格式文件-->
    <link rel="stylesheet" href="/static/css/register.css">
    <style>
        .err{
            color: red;
        }
</style>
</head>
<body>
    <div class="rg_layout">
        <div class="rg_left">
            <p>新用户注册</p>
            <p>USER REGISTER</p>
        </div>
        <div class="rg_center">
            <div class="rg_form">
                <form action="/test" method="post">
                {% csrf_token %}
                    <table>
                        <tr><!--label 标签的作用是当点击文字也会跳到文本输出框-->
                            <!--for属性与ID属性对应规定 label 绑定到哪个表单元素。-->
                            <td class="td_left"><label for="username">用户名</label> </td>
                            <td class="td_right"><input type="text" name="username" >
                                <span class="username_err err"></span>
                            </td>
                        </tr>
                        <tr>
                            <td class="td_left"><label for="password">密码</label> </td>
                            <td class="td_right"><input type="password" name="password" >
                            <span class="password_err err"></span>
                            </td>

                        </tr>
                        <tr><!--label 标签的作用是当点击文字也会跳到文本输出框-->
                            <td class="td_left"><label for="email">email</label> </td>
                            <td class="td_right"><input type="email" name="email" >
                            <span class="email_err err"></span>
                            </td>

                        </tr>
                        <tr>
                            <td class="td_left"><label for="name">姓名</label> </td>
                            <td class="td_right"><input type="text" name="name" >
                                <span class="name_err err"></span>
                            </td>

                        </tr>
                        <tr>
                            <td class="td_left"><label for="tel">手机号</label> </td>
                            <td class="td_right"><input type="text" name="tel" >
                                <span class="tel_err err"></span>
                            </td>

                        </tr>
                        <tr>
                            <td class="td_left">性别</td>
                            <td class="td_right">
                                <input type="radio" name="gender"  value="male">男
                                <input type="radio" name="gender"  value="female">女
                                <span class="gender_err err"></span>
{#                                加个span标签显示错误信息,默认为空值,err样式赋予红色字体   #}
                            </td>
                        </tr>
                        <tr>
                            <td class="td_left"><label for="birthday">出生日期</label> </td>
                            <td class="td_right"><input type="date" name="birthday" >
                                <span class="birthday_err err"></span>
                            </td>

                        </tr>
                        <tr>
{#                            <td class="td_left"><label for="checkcode">验证码</label> </td>#}
{#                            <td class="td_right">#}
{#                                <input type="text" name="username1" >#}
{#                                <img src="image/verify_code.jpg" >#}
{#                            </td>#}
                        </tr>
                        <tr>
                            <td colspan="2" align="center"  >
                                <div  >注册</div>
{#                                <input type="submit" value="注册" >#}
                            </td>
                        </tr>

                    </table>
                </form>
            </div>
        </div>
        <div class="rg_right">
            <p>已有账号?<a rel="nofollow" href="/login">立即登录</a></p>
        </div>
    </div>
</body>
<script src="/static/js/jquery-3.5.1.min.js"> </script>
<script>
    $("#btn_sub").click(function (){
        var data={}
        data['username']=$("#username").val()
        data['password']=$("#password").val()
        data['email']=$('#email').val()
        data['birthday']=$('#birthday').val()
        data['name']=$('#name').val()
        data['tel']=$('#tel').val()
        data['gender']=$('input:radio[name="gender"]:checked').val();
        $.ajax({
            data:data,
            dataType:"json",
            "type":"POST",
            "url":'/register',
            "success":function (arg) {
                if (arg.status == "ok") {
                    window.location.replace("/login")
                } else {
                    var err=arg.msg
                    for ( x in err)
                    {
                        $("."+x+"_err").text(err[x])

                    }
                    console.log("aaa")
                }
            }
        })
    })
</script>
</html>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.

debug:

登录后复制


1.forms的errors默认是'django.forms.utils.ErrorDict 数据格式
返回默认使用as_ul方法,可以改为as_json

        data=regform(request.POST)
        data.is_valid()
        data.errors.as_json()


2.form表单choies报错:famale is not one of the available choices
        排查后发现,前端传递的值有问题,把female写成了famale

3.form组件里面的password字段不能识别
        原因:未知
        解决:检查统一form里面字段参数的逗号等格式,重启下就好了


  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.