表单,在前端页面中属于最常见的一个东西了。基本上网站信息的提交都用到了表单,所以下面来学习Django中优雅的表单系统:Form
表单的主要作用是在网页上提供一个图形用户页面,用作采集和提供用户输入数据。
表单的基本结构: <form></form>
get:使用URL传参:http://服务器地址?name1 = value&name2=value2(?表示传递参数,?后面采用name=value的形式传递,多个参数之间,用&链接)URL传参不安全,所有信息可在地址栏看到,并且可以通过地址栏随机传递其他数据。URL传递数据量有限,只能传递少量数据。
post:使用HTTP请求传递数据。URL地址栏不可见,比较安全。且传递数据量没有限制。
表单提交中中get和post方式的区别
input标签是输入框,是表单中最重要的部分。
<form action="外部链接路径".method="get/post".name="#"> <input type="text">输入文本框 <input type="password">输入密码框 <input type="button">输入按钮 <input type="reset">重置 <input type="submit">提交 <input type="file">文件 <input type="checkbox">多选框 <input type="checkbox" checked>代表多选框默认选择项 <input type="radio">单选框,注意name需一样 <input type="date">时间 <input type="checkbox">多选框
name:是指名字,因为提交的是键值对,所以必须要指定名字,否则无法提交,即使提交了也没有意义。
value:文本框的内容,一般用在不能输入的类型中,如改变按钮的名字等。
placeholder:占位内容,通常用于显示
readonly:只读模式,设置后无法修改输入框的内容
disabled:禁用状态
size:由于输入框是单行的,所以只能设置宽度
maxlength:限制输入框最大输入的字符个数
开发中表单提交是很常见的,表单的提交方式也有很多种。
1,使用submit按钮提交表单
<input type="submit" value="提交">
2,使用button按钮提交表单
<input type="button" value="提交">
3,使用js进行表单提交,将form表单进行标记,将form表单中的某个元素设置成点击事件,点击时候调用js函数,再用JS。
$("#id").submit()
label元素不会向用户呈现任何特殊效果。不过,它为鼠标用户改进了可用性。如果您在label元素内点击文本,就会触发此控件。也就是说,当用户选择该标签时,浏览器就会自动将焦点转到和标签相关的表单控件上。
<label> 标签的for属性应当与相关元素的id属性相同
带有两个输入字段和相关标记的简单HTML表单:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<table>
<tr>
<td><label for="username">用户名: </label></td>
<td><input type="text" name="username" id="username"></td>
</tr>
<tr>
<td><label for="username">密码: </label></td>
<td><input type="password" name="password" id="password"></td>
</tr>
<tr>
<td><label for="repassword">密码确认: </label></td>
<td><input type="password" name="password" id="repassword"></td>
</tr>
<tr>
<td><label for="_basketball">爱好: </label></td>
<td>
<label><input type="checkbox" value="basketball" name="‘hobby" id="_basketball">basketball</label>
<label><input type="checkbox" value="football" name="‘hobby" id="_basketball">football</label>
<label><input type="checkbox" value="skating" name="‘hobby" id="_basketball">skating</label>
</td>
</tr>
<tr>
<td><label for="_boy">性别:</label></td>
<td>
<label><input type="radio" value="boy" name="sex" id="_boy">boy</label>
<label><input type="radio" value="girl" name="sex" >girl</label>
</td>
</tr>
<tr>
<td><label for="email">邮箱:</label></td>
<td><input type="text" name="email" id="email"></td>
</tr>
<tr>
<td><label for="address">住址:</label></td>
<td><input type="text" name="address" id="address"></td>
</tr>
</table>
</body>
</html>
Field
required=True, 是否允许为空
widget=None, HTML插件
label=None, 用于生成Label标签或显示内容
initial=None, 初始值
help_text=‘‘, 帮助信息(在标签旁边显示)
error_messages=None, 错误信息 {‘required‘: ‘不能为空‘, ‘invalid‘: ‘格式错误‘}
show_hidden_initial=False, 是否在当前插件后面再加一个隐藏的且具有默认值的插件(可用于检验两次输入是否一直)
validators=[], 自定义验证规则
localize=False, 是否支持本地化
disabled=False, 是否可以编辑
label_suffix=None Label内容后缀
CharField(Field)
max_length=None, 最大长度
min_length=None, 最小长度
strip=True 是否移除用户输入空白
IntegerField(Field)
max_value=None, 最大值
min_value=None, 最小值
FloatField(IntegerField)
...
DecimalField(IntegerField)
max_value=None, 最大值
min_value=None, 最小值
max_digits=None, 总长度
decimal_places=None, 小数位长度
BaseTemporalField(Field)
input_formats=None 时间格式化
DateField(BaseTemporalField) 格式:2015-09-01
TimeField(BaseTemporalField) 格式:11:12
DateTimeField(BaseTemporalField)格式:2015-09-01 11:12
DurationField(Field) 时间间隔:%d %H:%M:%S.%f
...
RegexField(CharField)
regex, 自定制正则表达式
max_length=None, 最大长度
min_length=None, 最小长度
error_message=None, 忽略,错误信息使用 error_messages={‘invalid‘: ‘...‘}
EmailField(CharField)
...
FileField(Field)
allow_empty_file=False 是否允许空文件
ImageField(FileField)
...
注:需要PIL模块,pip3 install Pillow
以上两个字典使用时,需要注意两点:
- form表单中 enctype="multipart/form-data"
- view函数中 obj = MyForm(request.POST, request.FILES)
URLField(Field)
...
BooleanField(Field)
...
NullBooleanField(BooleanField)
...
ChoiceField(Field)
...
choices=(), 选项,如:choices = ((0,‘上海‘),(1,‘北京‘),)
required=True, 是否必填
widget=None, 插件,默认select插件
label=None, Label内容
initial=None, 初始值
help_text=‘‘, 帮助提示
ModelChoiceField(ChoiceField)
... django.forms.models.ModelChoiceField
queryset, # 查询数据库中的数据
empty_label="---------", # 默认空显示内容
to_field_name=None, # HTML中value的值对应的字段
limit_choices_to=None # ModelForm中对queryset二次筛选
ModelMultipleChoiceField(ModelChoiceField)
... django.forms.models.ModelMultipleChoiceField
TypedChoiceField(ChoiceField)
coerce = lambda val: val 对选中的值进行一次转换
empty_value= ‘‘ 空值的默认值
MultipleChoiceField(ChoiceField)
...
TypedMultipleChoiceField(MultipleChoiceField)
coerce = lambda val: val 对选中的每一个值进行一次转换
empty_value= ‘‘ 空值的默认值
ComboField(Field)
fields=() 使用多个验证,如下:即验证最大长度20,又验证邮箱格式
fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),])
MultiValueField(Field)
PS: 抽象类,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用
SplitDateTimeField(MultiValueField)
input_date_formats=None, 格式列表:[‘%Y--%m--%d‘, ‘%m%d/%Y‘, ‘%m/%d/%y‘]
input_time_formats=None 格式列表:[‘%H:%M:%S‘, ‘%H:%M:%S.%f‘, ‘%H:%M‘]
FilePathField(ChoiceField) 文件选项,目录下文件显示在页面中
path, 文件夹路径
match=None, 正则匹配
recursive=False, 递归下面的文件夹
allow_files=True, 允许文件
allow_folders=False, 允许文件夹
required=True,
widget=None,
label=None,
initial=None,
help_text=‘‘
GenericIPAddressField
protocol=‘both‘, both,ipv4,ipv6支持的IP格式
unpack_ipv4=False 解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1, PS:protocol必须为both才能启用
SlugField(CharField) 数字,字母,下划线,减号(连字符)
...
UUIDField(CharField) uuid类型
...
TextInput(Input) NumberInput(TextInput) EmailInput(TextInput) URLInput(TextInput) PasswordInput(TextInput) HiddenInput(TextInput) Textarea(Widget) DateInput(DateTimeBaseInput) DateTimeInput(DateTimeBaseInput) TimeInput(DateTimeBaseInput) CheckboxInput Select NullBooleanSelect SelectMultiple RadioSelect CheckboxSelectMultiple FileInput ClearableFileInput MultipleHiddenInput SplitDateTimeWidget SplitHiddenDateTimeWidget SelectDateWidget
widget是form表单最重要的参数之一,指定渲染Widget时使用的widget类,举个例子:就是说这个form字段在HTML页面中为文本输入框,密码输入框,单选框,多选框。。。。。
pwd = forms.CharField(
min_length=6,
label="密码",
widget=forms.widgets.PasswordInput()
单radio值为字符串
user_type_choice = (
(0, u‘普通用户‘),
(2, u‘高级用户‘),
)
user_type = forms.IntegerField(initial=2,
widget=forms.widgets.RadioSelect(choices=user_type_choice,))

user_type_choice = (
(0, u‘普通用户‘),
(2, u‘高级用户‘),
)
user_type = forms.IntegerField(initial=2,
widget=forms.widgets.Select(choices=user_type_choice,))

user_type_choice = (
(0, u‘普通用户‘),
(2, u‘高级用户‘),
)
user_type = forms.IntegerField(initial=[1, ],
widget=forms.widgets.SelectMultiple(choices=user_type_choice,))

user_type = forms.CharField(widget=forms.widgets.CheckboxInput())

值为列表
user_type_choice = (
(0, u‘普通用户‘),
(2, u‘高级用户‘),
)
user_type = forms.CharField( initial=[2, ],
widget=forms.widgets.CheckboxSelectMultiple(
choices=user_type_choice,
))

在使用选择标签的时候,需要注意choices的选项可以从数据库获取,但是由于是静态子弹,获取的值无法更新,那么需要自定义构造方法从而达到目的。
首先我们看一下下面的案例:
#/usr/bin/env python
#-*- coding:utf-8 -*-
from django.shortcuts import render
# Create your views here.
def user_list(request):
host = request.POST.get(‘host‘)
port = request.POST.get(‘port‘)
mail = request.POST.get(‘mail‘)
mobile = request.POST.get(‘mobile‘)
#这里有个问题,如果,这个from表单有20个input,你在这里是不是的取20次?
#验证:
#输入不能为空,并且有的可以为空有的不可以为空
#如果email = 11123123 这样合法吗?
#如果mobile = 11123123 这样合法吗?
#如果ip = 11123123 这样合法吗?
‘‘‘
你在这里是不是需要做一大堆的输入验证啊?并且有很多这种页面会存在这种情况,如果每个函数都这样做估计就累死了
‘‘‘
return render(request,‘user_list.html‘)
针对于上面的问题,如何解决呢?——那就是Form表单
通常提交表单数据就是由HTML表单向后台传递信息,后台通过request.GET() 或者 request.POST()获取。
建一个Blog项目,并在template下新建两个html页面,一个注册页面命名为register,一个欢迎页面为welcome。
1,创建project django-admin startproject Blog 2,创建APP python manage.py startapp user1 3,修改settings配置 在INSTALLED_APPS中添加APP:user1 在TEMPLATES中查看“DIRS”内容,如果有template,请保持原样,如果没有,则添加 ‘DIRS‘: [os.path.join(BASE_DIR, ‘templates‘)]
项目目录如下:

给template下两个html页面register和welcome填充内容。
register.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>register</title>
</head>
<body>
<form action="/user/register/" method="post">
{% csrf_token %}
<p>用户名:<input type="text" name="username"></p>
<p>密码: <input type="password" name="password"></p>
<input type="submit" value="submit">
</form>
</body>
</html>

welcome.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>welcome</title>
</head>
<body>
<h1>welcome to this page</h1>
</body>
</html>
在user1/models.py中创建表结构,代码如下:
from django.db import models
# Create your models here.
class BlogUser(models.Model):
username = models.CharField(max_length=200, unique=True)
password = models.CharField(max_length=200)
ChariField 字符串字段,用于较短的字符串,需要max_length来指定VARCHAR数据库字段的大小。
同时,修改Bolg/settings.py的内容:
找到下面这段代码,并注释掉:
DATABASES = {
‘default‘: {
‘ENGINE‘: ‘django.db.backends.sqlite3‘,
‘NAME‘: os.path.join(BASE_DIR, ‘db.sqlite3‘),
}
}
然后写入下面代码:
import pymysql
pymysql.install_as_MySQLdb()
DATABASES = {
‘default‘: {
# 这里可以指定使用的数据库类型,例如mysql
‘ENGINE‘: ‘django.db.backends.mysql‘,
‘NAME‘: ‘blog_demo‘,
‘USER‘:‘root‘,
‘PASSWORD‘:‘******‘,
‘HOST‘:‘localhost‘,
‘PORT‘:‘3306‘,
}
}
如果这里不熟悉请参考:Django连接MySQL数据库
并且,映射数据库,这一步不能忘记:
在终端创建表 1,生成同步数据库的代码: python manage.py makemigrations 2,同步数据库(也就是对数据库执行真正的迁移动作): python manage.py migrate

我们重构views.py中的代码
from django.shortcuts import render
# Create your views here.
from user1.models import BlogUser
def register(request):
if request.method ==‘GET‘:
return render(request, ‘register.html‘)
elif request.method == ‘POST‘:
bloguser = BlogUser()
bloguser.username = request.POST.get(‘username‘)
bloguser.password = request.POST.get(‘password‘)
bloguser.save()
return render(request, ‘welcome.html‘)
get() 中的username和password是取的register 里的username的值。以获取(request)注册的信息,保存为save()。
然后运行项目,并注册信息,代码如下:
1, 运行项目 python manage.py runserver 2,在浏览器中输入: http://127.0.0.1:8000/user/register/
然后我们注册信息,并提交。我们可以看到上面的register.html中用户名是唯一的,所以当我们注册相同的名称时候回报错500,并且传输失败。
下面在数据库看一下我们的注册信息

其中,3,5不显示,因为我输入了相同的用户名。如果输入不重复,则显示下面界面。

在上面的基础上,我们再实现一个表单流程,继续了解form表单的知识。
from django.shortcuts import render, HttpResponse
# Create your views here.
from django import forms
class LoginForm(forms.Form):
account = forms.CharField()
password = forms.CharField()
email = forms.CharField()
def login(request):
if request.method == "POST":
form = LoginForm(request.POST)
if form.is_valid():
return HttpResponse("登录成功")
else:
form = LoginForm()
return render(request, ‘user6/login.html‘,{‘form‘:form})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div align="center" style="height: 400px; width: 100px;">
<form action="#" method="post">
{% csrf_token %}
{{ form }}
<button type="submit" id="sum">submit</button>
</form>
</div>
</body>
</html>
然后,去配置urls一些基本的配置(比如模板,路由等)。
我们直接点开login.html 内容如下:

我们打开Django项目,从127.0.0.1:8000/user6/login/ 进入,如下:

直接访问地址就显示出这样一个简单的界面,由HTML文件可以看到并没有js代码对数据有效性进行验证,我们随机输入账号,密码,邮箱,则提交,显示登陆成功。如下:

从上面的代码我们发现,前端一个 {{ form }} 就能做出一个完整强大的表单。但是我们只能用account password 做名称吗?
不是的,这里我们可以定制其名字,并且可以限制输入位数等等各种操作。
在form里有一个参数:error_messages 在他这里就可以定义报错内容
class UserInfo(forms.Form):
# required是否可以为空,如果为False,则说明可以为空
email = forms.EmailField(required=False,error_messages={‘required‘:u‘邮箱不能为空‘})
# 如果required 不写默认为Ture
host = forms.CharField(error_messages={‘required‘:u‘主机不能为空‘})
port = forms.CharField(error_messages={‘required‘:u‘端口不能为空‘})
mobile = forms.CharField(error_messages={‘required‘:u‘手机不能为空‘})

class UserInfo(forms.Form):
# required是否可以为空,如果为False,则说明可以为空
email = forms.EmailField(required=False,error_messages={‘required‘:u‘邮箱不能为空‘})
# 如果required 不写默认为Ture
host = forms.CharField(error_messages={‘required‘:u‘主机不能为空‘})
port = forms.CharField(error_messages={‘required‘:u‘端口不能为空‘})
mobile = forms.CharField(error_messages={‘required‘:u‘手机不能为空‘},
# 这里默认是TextInput 标签
widget = forms.TextInput(attrs={‘class‘:‘form-control‘,
‘placeholder‘:u‘手机号码‘}))

class UserInfo(forms.Form):
# required是否可以为空,如果为False,则说明可以为空
email = forms.EmailField(required=False,error_messages={‘required‘:u‘邮箱不能为空‘})
# 如果required 不写默认为Ture
host = forms.CharField(error_messages={‘required‘:u‘主机不能为空‘})
port = forms.CharField(error_messages={‘required‘:u‘端口不能为空‘})
mobile = forms.CharField(error_messages={‘required‘:u‘手机不能为空‘},
# 这里默认是TextInput 标签
widget = forms.TextInput(attrs={‘class‘:‘form-control‘,
‘placeholder‘:u‘手机号码‘}))
# 我们再这里新增一个备份
memo = forms.CharField(required=False,
widget=forms.Textarea(attrs={‘class‘:‘form-control‘,‘placeholder‘:u‘备份‘}))
同样的HTML代码也要新增:
<form action="/user_list/" method="post">
<p>主机 : {{ obj.host }}<span>{{ errors.host }}</span></p>
<p>端口 : {{ obj.port }}<span>{{ errors.port }}</span></p>
<p>邮箱 : {{ obj.email }}<span>{{ errors.email }}</span></p>
<p>手机 : {{ obj.mobile }}<span>{{ errors.mobile }}</span></p>
<p>备注:{{ obj.memo }}<span>{{ errors.memo }}</span></p>
<input type="submit" value="submit">
</form>

import re
from django import forms
from django.core.exceptions import ValidationError
def mobile_validate(value):
# 正则匹配
mobile_re = re.compile(r‘^(13[0-9]|15[0123456789]|18[0-9]|14[57])[0-9]{8}$‘)
if not mobile_re.match(value):
raise ValidationError("手机号码格式错误")
class UserInfo(forms.Form):
# required是否可以为空,如果为False,则说明可以为空
email = forms.EmailField(required=False, error_messages={‘required‘: u‘邮箱不能为空‘})
host = forms.CharField(error_messages={‘required‘: u‘主机不能为空‘})
port = forms.CharField(error_messages={‘required‘: u‘端口不能为空‘})
mobile = forms.CharField(# 应用我们自己定义的规则
validators=[mobile_validate,],
error_messages={‘required‘: u‘手机不能为空‘},
# 这里默认使用TextInput 标签
widget=forms.TextInput(attrs={‘class‘: ‘form-control‘,
‘placeholder‘: u‘手机号码‘}))
# 我们新增一个备份
memo = forms.CharField(required=False,
widget=forms.TextInput(attrs={‘class‘: ‘form-control‘,
‘placeholder‘: u‘备份‘}))
def user_list(request):
# 创建了这个对象
obj = UserInfo()
if request.method == ‘POST‘:
# 获取用户输入一句话就搞定
user_input_obj = UserInfo(request.POST)
# 判断用户输入是否合法
if user_input_obj.is_valid():
# 获取用户输入
data = user_input_obj.clean()
print(data)
else:
# 如果发生错误,捕获异常
# 这里原来什么都没写,默认是ul的样式,默认是as_ul(),
# 如果我们写成as_data()返回的就是一个原生的字符串
# 还有一个as_json
error_msg = user_input_obj.errors.as_data()
# 然后把错误信息返回
print(error_msg)
# 然后把对象传给html,在把错误信息传递过去
return render(request, ‘user6/register.html‘, {‘obj‘: obj, ‘errors‘: error_msg,})
# 将对象传给html
return render(request, ‘user6/register.html‘, {‘obj‘:obj,})
当我们输入不合法的时候,或者不是email格式的时候,会出现如下错误:

这样后端我们就有一套验证的机制了,就是通过is_valid()来判断用户输入是否合法!如果不合法就把返回的信息发送出去,如果合法获取数据,继续操作即可!
class UserInfo(forms.Form):
user_type_choice = (
(0,u‘普通用户‘),
(1,u‘高级用户‘),
)
user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice,
attrs={‘class‘:‘form-control‘}))
# required是否可以为空,如果为False,则说明可以为空
email = forms.EmailField(required=False,error_messages={‘required‘:u‘邮箱不能为空‘})
# 如果required 不写默认为Ture
host = forms.CharField(error_messages={‘required‘:u‘主机不能为空‘})
port = forms.CharField(error_messages={‘required‘:u‘端口不能为空‘})
mobile = forms.CharField(error_messages={‘required‘:u‘手机不能为空‘},
# 这里默认是TextInput 标签
widget = forms.TextInput(attrs={‘class‘:‘form-control‘,
‘placeholder‘:u‘手机号码‘}))
# 我们再这里新增一个备份
memo = forms.CharField(required=False,
widget=forms.Textarea(attrs={‘class‘:‘form-control‘,‘placeholder‘:u‘备份‘}))
HTML内更改如下:
<form action="/user_list/" method="post">
<p>用户类型:{{ obj.user_type }}<span>{{ errors.user_type }}</span></p>
<p>主机 : {{ obj.host }}<span>{{ errors.host }}</span></p>
<p>端口 : {{ obj.port }}<span>{{ errors.port }}</span></p>
<p>邮箱 : {{ obj.email }}<span>{{ errors.email }}</span></p>
<p>手机 : {{ obj.mobile }}<span>{{ errors.mobile }}</span></p>
<p>备注:{{ obj.memo }}<span>{{ errors.memo }}</span></p>
<input type="submit" value="submit">
</form>

这个后端验证是必须要有验证机制的,前端可以不写但是后端必须写,前端的JS是可以被禁用掉的,在实际的生产环境中比如登录和验证的时候,我们一般都使用 JQuery+AJAX 来判断用户的输入是否为空,假如JS被禁用(浏览器端可以设置禁用JS效果)的话,我们这个认证屏障是不是就消失了呢?(虽然一般不会禁用但是还是存在风险),所以我们一般做两种认证,在前端做一遍认证,在后端做一遍认证。

import re
from django import forms
from django.core.exceptions import ValidationError
#自定义方法
def mobile_validate(value):
mobile_re = re.compile(r‘^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$‘) #正则匹配
if not mobile_re.match(value):
raise ValidationError(‘手机号码格式错误‘) #如果没有匹配到主动出发一个错误
class UserInfo(forms.Form):
user_type_choice = (
(0, u‘普通用户‘),
(1, u‘高级用户‘),)
user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice,attrs={‘class‘:‘form-control‘}))
email = forms.EmailField(required=True,error_messages={‘required‘:u‘邮箱不能为空‘}) #required是否可以为空,如果为False说明可以为空
host = forms.CharField(error_messages={‘required‘:u‘主机不能为空‘}) #如果required不写默认为Ture
port = forms.CharField(error_messages={‘required‘:u‘端口不能为空‘})
#默认mobile里有一个默认为空的机制,我们在原有的参数里增加怎们自定义的方法
mobile = forms.CharField(validators=[mobile_validate,],#应用咱们自己定义的规则
error_messages={‘required‘:u‘手机不能为空‘},
widget=forms.TextInput(attrs={‘class‘:‘form-control‘,‘placeholder‘:u‘手机号码‘})
#这里默认是TextInput,标签
)
#咱们在新增一个备注
memo = forms.CharField(required=False,
widget=forms.Textarea(attrs={‘class‘:‘form-control‘,‘placeholder‘:u‘备注‘}))
def user_list(request):
obj = UserInfo() #创建了这个对象
if request.method == ‘POST‘:
#获取用户输入一句话就搞定
user_input_obj = UserInfo(request.POST)
if user_input_obj.is_valid(): #判断用户输入是否合法
data = user_input_obj.clean() #获取用户输入
print data
else:
#如果发生错误,捕捉错误
error_msg = user_input_obj.errors.as_data()#这里原来什么都没写,默认是ul的样式,默认是as_ul(),如果我们写成as_data()返回的就是一个原生的字符串
#还有一个as_json
print error_msg #打印一下然后看下他的类型
#然后把错误信息返回
return render(request,‘user_list.html‘,{‘obj‘:obj,‘errors‘:error_msg,})#然后把对象传给html,在把错误信息传递过去
return render(request,‘user_list.html‘,{‘obj‘:obj,})#然后把对象传给html
def clean_username(self): # 函数名必须已clean_字段名的格式
user = self.cleaned_data.get("username")
if not User.objects.filter(username=user):
if not user.isdigit():
if re.findall(r"^[A-Za-z0-9_\-\u4e00-\u9fa5]+$",user):
return user # 通过检测,原数据返回 self.cleaned_data.get("username")
else:
raise ValidationError(‘用户名存在非法字符‘) # 没通过检测抛出错误,必须用ValidationError
else:
raise ValidationError("用户名不能为纯数字")
else:
raise ValidationError("该用户名已存在")
def clean(self): # 必须命名为clean
# 判断是否都通过检测,都不为None
if self.cleaned_data.get("password") and self.cleaned_data.get("check_pwd"):
if self.cleaned_data.get("password") == self.cleaned_data.get("check_pwd"):
return self.cleaned_data # 如果两次密码相同,返回干净的字典数据
else:
raise ValidationError("输入密码不一致") # 没通过检测返回异常信息
else:
return self.cleaned_data
参考文献:https://blog.csdn.net/qq_42068900/article/details/80904596
原文:https://www.cnblogs.com/wj-1314/p/10592822.html