前戏
我们之前是通过html的form表单来提交数据,提交到服务器之后,我们需要对某些字段做判断,比如用户名密码的长度,格式正确不正确。如果用户输入的内容不正确就要在页面上显示对应的错误信息。当然我们可以通过if..elif来进行判断,但是这样写的话,代码很冗余。而Django的form组件就提供了我们这些校验的功能。
普通验证
先来看看不使用form来判断用户名不能小于6位长度是怎么做的
视图函数
def register(request): error_msg = '' if request.method=="POST": user = request.POST.get('user') pwd = request.POST.get('pwd') if len(user)<6: error_msg='用户名长度不符合' else: error_msg = '注册成功' return render(request, 'register.html',{'error_msg': error_msg})
html文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="" method="post"> {% csrf_token %} <p> 用户名:<input type="text" name="user"> </p> <p> 密码:<input type="text" name="pwd"> </p> <p> <input type="submit" value="提交"> <p style="color: red">{{ error_msg }}</p> </p> </form> </body> </html>
使用form组件进行验证
使用form验证,需要定义一个类,我们在views.py定义一个RegisterForm类
from django import forms class RegisterForm(forms.Form): # 继承Form类 user = forms.CharField(label='用户名') pwd = forms.CharField(label='密码')
在修改视图函数
def register(request): form_obj = RegisterForm() # 实例化类 if request.method == "POST": # 实例化form对象的时候,把post提交过来的数据直接传进去 form_obj = RegisterForm(request.POST) # form_obj就是提交的数据 # 调用form_obj校验数据的方法 if form_obj.is_valid(): return HttpResponse("注册成功") return render(request, 'register.html',{'form_obj': form_obj})
修改html文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="" method="post"> {% csrf_token %} {{ form_obj.as_p }} <button>注册</button> </form> </body> </html>
这样,页面就生成了两个input框
我们可以通过 form_obj.cleaned_data 来获取页面输入的数据,这个必须要放在 form_obj.is_valid() 下面,要不然会报错。
上面的html文件还可以这样写
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="" method="post"> {% csrf_token %} <p> {{ form_obj.user.label }} //只获取label值 {{ form_obj.user }} //一个input框 </p> <p> {{ form_obj.pwd.label }} {{ form_obj.pwd }} </p> <button>注册</button> </form> </body> </html>
接下来我们给字段加上长度校验,更改RegisterForm
class RegisterForm(forms.Form): # 继承Form类 user = forms.CharField(label='用户名', min_length=6) pwd = forms.CharField(label='密码', min_length=6)
修改html文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="" method="post" novalidate> novalidate不校验 {% csrf_token %} <p> {{ form_obj.user.label }} {{ form_obj.user }} </p> <p> {{ form_obj.pwd.label }} {{ form_obj.pwd }} </p> <button>注册</button> {{ form_obj.errors }} 全局的错误提示 </form> </body> </html>
上面的form_obj.errors是全局的校验,用户名和密码都会校验,如果只想校验某个字段,只需要按照下面的方式写
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="" method="post" novalidate> {% csrf_token %} <p> {{ form_obj.user.label }} {{ form_obj.user }} {{ form_obj.user.errors }} 只对user输入框做校验 {{ form_obj.user.errors.0 }} 取错误的第一个 </p> <p> {{ form_obj.pwd.label }} {{ form_obj.pwd }} </p> <button>注册</button> </form> </body> </html>
常用字段和插件
插件是用于生成HTML的,例如上面生成的input框默认类型是“text”,我们可以使用插件让生成的input框是“password”
initial
input框里的默认值
from django import forms class RegisterForm(forms.Form): # 继承Form类 user = forms.CharField(label='用户名', min_length=6, initial='zouzou' )
error_message
自定义错误信息
from django import forms class RegisterForm(forms.Form): # 继承Form类 user = forms.CharField(label='用户名', min_length=6, initial='zouzou', error_messages={ "min_length":"长度不符合要求", "required":"不能为空", "invalid":"格式错误" } )
password
上面生成的input类型是type,我们使用插件来让生成的input标签的类型为pasword
首先需要导入
from django.forms import widgets
from django import forms from django.forms import widgets class RegisterForm(forms.Form): # 继承Form类 pwd = forms.CharField(label='密码', min_length=6, widget=widgets.PasswordInput() )
当然,也可以设置属性
widget=forms.widgets.PasswordInput(attrs={'class': 'c1'})
ChoiceField
from django import forms from django.forms import widgets class RegisterForm(forms.Form): # 继承Form类 gender = forms.ChoiceField( choices=(("1","男"),("2","女")) )
默认是个下拉框,可以添加RadioSelect让它成为单选框
from django import forms from django.forms import widgets class RegisterForm(forms.Form): # 继承Form类 gender = forms.ChoiceField( choices=(("1","男"),("2","女")), widget=widgets.RadioSelect )
也可以让它成为一个多选
单选checkbox
from django import forms from django.forms import widgets class RegisterForm(forms.Form): # 继承Form类 gender = forms.ChoiceField( label="是否记住密码", initial="checked", widget=widgets.CheckboxInput() )
多选checkbox
from django import forms from django.forms import widgets class RegisterForm(forms.Form): # 继承Form类 gender = forms.ChoiceField( choices=((1, "篮球"), (2, "足球"), (3, "双色球"),), label="爱好", initial=[1, 3], # 默认选择1和3 widget=forms.widgets.CheckboxSelectMultiple() )
上面的是写死的,我们可以从数据库中获取数据
from django import forms from django.forms import widgets from appTest01 import models class RegisterForm(forms.Form): # 继承Form类 gender = forms.ChoiceField( choices=models.Press.objects.all().values_list('id','name'), # 从数据库中获取 label="性别", widget=forms.widgets.CheckboxSelectMultiple() )
需要说明的是,这样获取到的数据是项目重启之后再数据库里存在的值,如果项目启动之后你在数据库添加了新的数据,它不会显示在页面上的,如果想显示,我们就要重写构造方法
from django import forms from django.forms import widgets from appTest01 import models class RegisterForm(forms.Form): # 继承Form类 def __init__(self,*args, **kwargs): super().__init__(*args, **kwargs) self.fields['gender'].choices=models.Press.objects.all().values_list('id','name') gender = forms.ChoiceField( # choices=models.Press.objects.all().values_list('id','name'), # 从数据库中获取 label="爱好", widget=forms.widgets.CheckboxSelectMultiple() )
我们来看下self.fields是什么
print(self.fields) OrderedDict([('user', <django.forms.fields.CharField object at 0x048D6B10>), ('pwd', <django.forms.fields.CharField object at 0x048D6B50>), ('gender', <django.forms.fields.ChoiceField object at 0x048D6B90>)])
其余的内置字段