Django教程--Form表单
Django教程–Form表单
前面我们已经了解如何在django中使用GET、POST传递数据,但是我们并没有对用户提交的数据进行验证(为何需要验证大家都懂得),对于验证我们可以自己写相关代码进行判断(最基本也有效的方法),但是django作为一个集大成的全面框架,为我们提供了一种更优雅简单的方式,那就是今天的主角–Form,Form不仅仅具有数据验证功能,还可以生成用于提交的html标签,接下来我们就来了解一下如何使用Form。
Form基本使用
按照惯例,我们先来段代码演示如何使用,接着前面的PostParams工程,我们在app目录下新建forms.py文件,用来存放Form表单的代码,代码如下:
from django import forms
class RegisterForm(forms.Form):
username=forms.CharField(label='username',max_length=20,required=True,error_messages={'required':'username cannot be null'})
password=forms.CharField(label='password',widget=forms.PasswordInput,required=True,error_messages={'required':'password cannot be null'})
email=forms.EmailField(label='email',required=True,
error_messages={'required': u'email cannot be null','invalid': u'email format is wrong'},
widget=forms.TextInput(attrs={'class': "form-control", 'placeholder': u'email'}))
image=forms.ImageField(label='headimage',required=False)
从代码可以看到,使用Form我们需要定义一个类继承自forms.Form,然后定义几个变量(forms以经为什么提供了多种输入框,甚至Email都有,对于Email会自己做个正则表达判断),需要注意变量名对应html表单的name属性,每个属性有不同的校验规则(下面会仔细介绍,暂时先具体看下用法),我们还可以自定义每个属性的widget和label(用于生成html标签)以及校验错误返回的信息。
接下来我们在views.py里新建一个视图函数代码如下:
def form_view(request):
if request.method=='GET':
register_form=RegisterForm()
return render(request,'form.html',{'form':register_form})
else:
register_form=RegisterForm(request.POST or None,request.FILES or None)
if register_form.is_valid():
return HttpResponse('username:'+register_form.cleaned_data['username']+'&password:'+register_form.cleaned_data['password']+'&email:'+register_form.cleaned_data['email'])
else:
return render(request, 'form.html', {'form': register_form})
当然我们也要建立对应的模板文件form.html代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form method="post" enctype="multipart/form-data" >
{%csrf_token%}
<p>{{form.username.label}}:{{form.username}}</p>
{%if form.errors.username%}
{{form.errors.username}}
{%endif%}
<p>{{form.password.label}}:{{form.password}}</p>
{%if form.errors.password%}
{{form.errors.password}}
{%endif%}
<p>{{form.email.label}}:{{form.email}}</p>
{%if form.errors.email%}
{{form.errors.email}}
{%endif%}
<P>{{form.image.label}}:{{form.image}}</P>
{%if form.errors.image%}
{{form.errors.image}}
{%endif%}
<input type="submit" value="Submit">
</form>
</body>
</html>
然后在urls.py中添加拦截
from django.conf.urls import patterns, include, url
from django.contrib import admin
from app.views import params_test, params_test_reg, params_post, form_view
urlpatterns = patterns('',
# Examples:
# url(r'^$', 'PostParams.views.home', name='home'),
# url(r'^blog/', include('blog.urls')),
url(r'^admin/', include(admin.site.urls)),
url(r'^params_test/$',params_test),
url(r'^params_test_reg/str(?P<str>\w+)page(?P<page>\d+)/$',params_test_reg),
url(r'^post/$',params_post),
url(r'^form/$',form_view),
)
启动服务器,输入http://127.0.0.1:8000/form/即可看到对应的表单,输入相关信息然后提交,如果满足验证要求,就会返回输入信息,当不满足的时候就会重新跳回表单界面并提示错误信息。
Form表单代码解析
上面我们已经展示了如何使用Form表单,接下来我们就来分析下上述代码并讲解Form。
先看Forms.py代码,Form为我们提供了格式各样的Field,用于应对各种各样的输入场景,例如本代码里面首先定义了四个需要提交的属性,每个属性各不相同,例如username需要文本输入框使用CharField,password同样需要文本输入框但是需要密码输入框,所以需要设置widget为密码输入框,对于email需要对输入的格式进行验证是否为正确的邮箱,所以需要EmailField,而对于图像文件则有对应的ImageField,对于这些属性我们还可以通过required指定哪些是必须输入(默认为True),我们还可以通过指定error_messages验证错误时显示的信息。
定义好表单后我们需要在视图函数中使用该表单,例如本例中先判断是否为get请求,如果为get请求就创建表单然后传给模板,在模板中我们只需使用{{}}标签输出表单对应的属性,然后就会自动渲染出该属性对应的widget的代码,我们可以更改widget甚至自定义widget来达到自己的个性化网页输入需求,当然我们还要判断当前表单是否有验证错误,如果发生错误该表单的errors即会有对应的错误信息(如form.errors.username)。
当我们提交表单的时候,视图函数通过request.POST(如果提交方式为POST,为GET提交请使用request.GET),request.FILES(如果提交包含文件)自动创建好表单,然后调用is_valid()进行验证表单输入,没有错误则返回输入信息,发生错误就返回表单提交页面并显示错误信息。
也许有人会说这种提交表单的方式过于笨重(在html模板中使用表单属性),不够灵活,有时候灵活和简便是不可多得的,框架提供功能越多,可能导致其更为笨重,但是这里我们也可以不使用这种笨重的方式,我们只需要将html表单里属性的name定义为和Form变量名一样即可,然后可以同样在后台创建接收输入的表单,例如本例html代码可以更改为
<form method="post" enctype="multipart/form-data" >
{%csrf_token%}
<p>username:<input id="id_username" maxlength="20" name="username" type="text" /></p>
<p>password:<input id="id_password" name="password" type="password" /></p>
<p>email:<input class="form-control" id="id_email" name="email" placeholder="email" type="text" /></p>
<P>headimage:<input id="id_image" name="image" type="file" /></P>
<input type="submit" value="Submit">
</form>
后台视图函数不需要任何更改也可正常使用。
对于Form验证Django为我们提供了一些通用的验证机制,如验证属性是否为空(required),长度验证(max_length,min_length),甚至电话号码email验证(EmailField,PhoneField)。
Form自定义验证
form验证流程
1.函数full_clean()依次调用每个field的clean()函数,该函数针对field的max_length,unique等约束进行验证,如果验证成功则返回值,否则抛出ValidationError错误。如果有值返回,则放入form的cleaned_data字典中。
2.如果每个field的内置clean()函数没有抛出ValidationError错误,则调用以clean_开头,以field名字结尾的自定义field验证函数。验证成功和失败的处理方式同步骤1。
3.最后,调用form的clean()函数——注意,这里是form的clean(),而不是field的clean()——如果clean没有错误,那么它将返回cleaned_data字典。
4.如果到这一步没有ValidationError抛出,那么cleaned_data字典就填满了有效数据。否则cleaned_data不存在,form的另外一个字典errors填上验证错误。在template中,每个field获取自己错误的方式是:{{ form.username.errors }}。
5.最后,如果有错误is_valid()返回False,否则返回True。
对于某些自定义验证规则我们可以通过重载上述clean_field函数或者clean函数来实现,例如对于用户注册需要验证用户名是否存在,两次密码输入是否相等,我们可以通过以下代码实现
from django import forms
class RegisterForm(forms.Form):
username=forms.CharField(label='username',max_length=20,required=True,error_messages={'required':'username cannot be null'})
password=forms.CharField(label='password',widget=forms.PasswordInput,required=True,error_messages={'required':'password cannot be null'})
password1 = forms.CharField(label='password1', widget=forms.PasswordInput, required=True,
error_messages={'required': 'password cannot be null'})
email=forms.EmailField(label='email',required=True,
error_messages={'required': u'email cannot be null','invalid': u'email format is wrong'},
widget=forms.TextInput(attrs={'class': "form-control", 'placeholder': u'email'}))
image=forms.ImageField(label='headimage',required=False)
def clean_username(self):
user = self.cleaned_data.get('username')
if user == 'cc':
raise forms.ValidationError('username exsite!')
return user
def clean(self):
cleaned_data = self.cleaned_data
pwd = cleaned_data['password']
pwd2 = cleaned_data['password1']
print(pwd, pwd2)
if pwd != pwd2:
raise forms.ValidationError('the password you input is not same')
return cleaned_data
我们重载clean_username函数来判断提交用户名是否为‘cc’,如果相等则验证失败并提示错误(通过 raise forms.ValidationError(‘username exsite!’)来实现),然后重载clean函数来判断两次输入密码是否相同。
Form文件接收
在上述例子中虽然使用了ImageField,但是并没有演示如何在视图函数中接收文件,对于文件来说我们同样可以通过form.cleaned_data[‘image’]来获取,然后可以获取上传文件的信息和实际文件并可以保存下来,代码如下:
myFile=register_form.cleaned_data['image']
destination = open(os.path.join(BASE_DIR, myFile.name), 'wb+')
for chunk in myFile.chunks():
destination.write(chunk)
destination.close()
和前一节的文件提交类似。
经过本节,我们了解了Form的基本使用–创建,渲染以及数据验证,其实Form的功能远不止于此,在后面我们会发现和Model结合Form具有更强大的功能,你只需要少量代码即可完成大量功能,这就是Django这种集大成框架的优势(当然会损失点灵活性),甚至就是python的宗旨(life is short,you need python),今天我们先了解到这里,谢谢大家支持。
参考链接
上一篇: 排序:插入排序
下一篇: CPP知识点笔记(二)