天天看点

利用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
           

这里把里面的属性值设置为跟前端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函数

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))           
<!DOCTYPE html>
<html lang="en">
<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" id="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" id="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" id="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" id="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" id="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" id="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" id="checkcode">#}
{#                                <img src="image/verify_code.jpg" id="img_check">#}
{#                            </td>#}
                        </tr>
                        <tr>
                            <td colspan="2" align="center"  >
                                <div id="btn_sub" >注册</div>
{#                                <input type="submit" value="注册" id="btn_sub">#}
                            </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.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里面字段参数的逗号等格式,重启下就好了
           

继续阅读