首先定义一个表单类(继承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函数
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))
regester.html部分
<!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 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>
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里面字段参数的逗号等格式,重启下就好了