您的位置:首页 > 编程语言 > Go语言

django搭建简单邮件发送系统——细说Form Validation(-)

2017-06-19 15:27 337 查看
对于Web而言,提交一个Form的操作是经常的。 Django自己有一个form库, django.forms, 这个库会对web显示到数据验证都提供支持,对于很多“错误”也是提供自动检验而不需要程序员额外花费代码。我们以一个“联系我们”的邮件系统为例来简单介绍一下django.forms库。

本操作环境:(2017.6.18日---今天剁手买了好多“6.18”😂)

OS: win7 (注意下文中的斜杠,我们知道在windows系统里是用'\'来表示路径的,但在django里要用unix 斜杠,我为了方便在下文中没有作区分,但读者要注意。)

python: 3.6.1

django: 1.11.2

创建项目与应用

django-admin startproject mysite

cd mysite

python manage.py startapp contactUs


将contactUs app增加到mysite/mysite/settings.py文件中,进行登记,这样django就知道有一个新的app产生了:

# Application definition

INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'contactUs',
)


创建Form类实例

在Django的一般惯例中,会把Form类创建在一个单独的文件中。在mysite/views.py同一个目录中创建forms.py文件,并写入以下代码:



#mysite/mysite/forms.py

from django import forms
class ContactUs(forms.Form):
subject = forms.CharField(max_length = 100)
email = forms.EmailField(required = False,label = 'Your e-mail address')
message = forms.CharField(widget = forms.Textarea)
def clean_message(self):
message = self.cleaned_data['message']
num_words = len(message.split())
if num_words < 4:
raise forms.ValidationError("Not enough words!")
return message


可以看出来,form类的语法和Django Model的语法类似,form 里的每个变量都要定义成一种"field"类型——CharField, EmailField都是forms类的属性。在这个定义中,我们要求subject域和message域是必填的,而email 域是可选填的,默认情况下每个域的requried = Ture, 所以我们要显式地对email域指定required = False。
在从django的Forms类翻译成最终的html文件后,会注意到CharFiled会被显示成html里的<input type = 'text'>,message应该被显示成text,可以通过设置该域的widget属性来将CharField类型最终显示成Text。在forms 框架中,你可以理解成在显示层面它把每个域都定义成一个“widget”,每个域都在默认的widget,你可以显性的定义自己的widget从而覆盖掉默认的widget。
django forms会根据每个域的定义值 来对其进行相应的验证(Validation)。比如message域定义成CharField, django forms在对该域进行完默认的CharField验证后,它会自动去寻找以clean_开头,并以域名结尾的函数,如果该函数存在(比如此例中的clean_message),它就会执行该函数中对数据的Validation。在这个例子中,我们要求message域的字符个数不能少于4个,否则会引发ValidationError消息。至于去验证某个域是否有输入值,django forms会默认验证,所以不需要我们另外写代码。
默认设置下,django 自动生成的form html页面时,它会把定义时的域名第一个字母大写,并用下划线连接第二个单词,这样的形式显示在html页面上。所以email 域就会以Email的形式显示在页面上,我们可以显性的定义label,这样就可以改变域名显示规则了(在django model里,是通过显性定义verbose_name来实现这个功能)。

p.p1 { margin: 0.0px 0.0px 2.0px 0.0px; font: 14.0px "Helvetica Neue"; color: #454545 }
span.s1 { font: 14.0px ".PingFang SC" }
创建Views

按照我的理解,views.py里就是定义数据是按照怎样的逻辑来呈现给用户。我们最终的目的就是要将数据显示给用户看,以供他们操作。打开mysite/mysite/views.py文件,写入:

#mysite/mysite/views.py

from django.http import Http404, HttpResponse, HttpResponseRedirect
from django.shortcuts improt render
from django.core.mail import send_mail, get_connection
from .forms import ContactUs
import datetime

def contact(request):
if request.method == 'POST':
form = ContactUs(request.POST)
if form.is_valid():
datas = form.cleaned_data
con = get_connection('django.core.mail.backends.console.EmailBackend')
send_mail(datas['subject'],datas['message'],datas.get('email', noreply@exmaple.com'), ['siteowner@example.com'], connection = con)
return HttpResponseRedirct('/contact/thanks/')
else:
form = ContactUs(initial = {'subject':'I love your site'})
return render(request, 'contact_form.html', {'form':form})


在这部分我们有很多需要解释,因为加入了许多新内容。


首先我们来讲一下HttpRequest.POST对象。这个对象返回的是一个类似于“字典”的对象,它里面包括的是form类的提交数据。如果想要得到除form类之外的数据,需要引用HttpRequest.body这个属性。HttpRequest.POST不会返回提交的文件类型数据,那个通过HttpRequest.Files对象来得到。如果web网页提交的Form没有任何数据,那么HttpRequest.POST就返回一个空的类“字典”对象,所以不能根据HttpRequest.POST对象来判断网页是否使用了POST方法,而应该是根据HttpRequest.method == 'POST'来判断。

再来讲讲Form类。Form类实例化后,这个实例就变成了一个“bound”的对象。对于一个“bound”对象,它有一个方法is_valid(),用来检验这个实例的数据是否有效。如果这个'bound'对象的数据是有效的,那么,这个对象还有一个“cleaned_data”属性,这个属性返回的结果是包含网页提交数据的字典形式。Django forms库不仅仅是对所写入的数据的有效性进行验证,而且还会把写入的有效数据转化成python里的数据类型。比如,它会把forms库里的CharField对象转化成python里的string对象,把IntegerField对象转化成python里的integer对象,把DateField对象转化成python里的datetime.date对象。在这段代码中没有对也可能的错误信息进行处理(比如用户没有填写subject或messages,直接提交数据),因为Forms类会自动对这些错误进行相应的处理,它会把所有的错误信息生成一个errors list。

“django.core.mail.backends.console.EmailBackend”这个EmailBackend很有用,因为它不需要我们搭建Email 服务器,就可以发送邮件。它会把邮件发送到系统终端系统(你可以在提交完form表单后检查系统的terminal窗口,可以看到发送的相应邮件)。

在发送完邮件后,web页面会转向/contact/thanks页面,这是通过HttpResponseRedirect()来实现的。

为了使页面更友好,当打开contact页面时,我们可以给subject设置一个初始值,通过设置Form实例的initial参数可以实现。


创建templates
 我们需要创建template来显示刚刚创建的form类。在mystie/contactUs里创建templates文件夹,这个文件夹是存放contactUs的模板文件的,然后新建contact_us.html文件,并输入:


#mysite/contactUs/templates/contact_us.html
<html>
<head>
<title>Contact us</title>

</head>
<body>
<h1>Contact us</h1>

{% if form.errors %}
<p style="color: red;">
Please correct the error{{ form.errors|pluralize }} below.
</p>
{% endif %}

<form action="" method="post" novalidate>
<table>
{{ form.as_table }}
</table>
{% csrf_token %}
<input type="submit" value="Submit">
</form>
</body>
</html>


首先要讲的是form.errors。在上一节中我们讲过,django的forms库会把web页面上的错误自动生成一个errors list,用户可以通过form实例来引用这个list。

{{form.errors | pluralize }} 。pluralize是一个template filter, 它会根据前面列表元素的个数来决定是否输出“s”字符,如果列表中元素个数多于1,它就会输出字符“s”

form表单的novalidate属性。如果浏览器用的是Html5技术(特别是Chrome),浏览器会自动对form表单提交的数据进行验证,但是我们希望是利用django的forms库进行数据的验证,所以我们不希望浏览器对数据进行验证,novalidate 这个属性就是这个用途。

{% csrf_token %} template tag。提交的POST数据,有Cross Site Request Forgeries的风险,django会自动处理这个风险。对于POST提交的数据的网页,它会返回HTTP 403Forbidden 页面。对于提交给本地的POST数据,加上{% csrf_token %}这个tag,可以不进入HTTP 403 Forbidden页面。

设置URL

在urls.py文件里,增加条目,完成从url到views的转换

from contactUs.views import contact

urlpatterns = [
# ...
url(r'^contact/$', contact),

]


启动服务

python manage.py runserver 80


注意:在发送完邮件后,页面会转向contact/thanks页面,这个页面我们在上述代码中没有实现,需要读者自己去实现

p.p1 { margin: 0.0px 0.0px 2.0px 0.0px; font: 14.0px ".PingFang SC"; color: #454545 }
span.s1 { font: 14.0px "Helvetica Neue" }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: