表单,在前端页面中属于最常见的一个东西了。基本上网站信息的提交都用到了表单,所以下面来学习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