ImageVerifierCode 换一换
格式:DOCX , 页数:15 ,大小:25.48KB ,
资源ID:4946469      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/4946469.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(第七章 表单处理.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

第七章 表单处理.docx

1、第七章 表单处理The Django BookAbout | Comment help | Contact us | Errata | Buy the print version on A 已完成 93段 共有 93段 完成度 100% | 中英文对照 | 英文 | 中文 | 上一章 | 目 录 | 下一章 | 翻译 | 第七章 表单处理本章作者是Simon Willison经过上一章,你应该对简单网站有个全面的认识。这一章,来处理web开发的下一个难题:建立用户输入的视图。我们会从手工打造一个简单的搜索页面开始,看看怎样处理浏览器提交而来的数据。然后我们开始使用Django的forms框架。

2、搜索在web应用上,有两个关于搜索获得巨大成功的故事:Google和Yahoo,通过搜索,他们建立了几十亿美元的业务。几乎每个网站都有很大的比例访问量来自这两个搜索引擎。甚至,一个网站是否成功取决于其站内搜索的质量。因此,在我们这个网站添加搜索功能看起来好一些。开始,在URLconf (mysite.urls )添加搜索视图。添加类似 (rsearch/$,mysite.books.views.search) 设置URL模式。下一步,在视图模块(mysite.books.views )中写这个 search 视图:from django.db.models import Qfrom djang

3、o.shortcuts import render_to_responsefrom models import Bookdef search(request): query = request.GET.get(q, ) if query: qset = ( Q(title_icontains=query) | Q(authors_first_name_icontains=query) | Q(authors_last_name_icontains=query) ) results = Book.objects.filter(qset).distinct() else: results = re

4、turn render_to_response(books/search.html, results: results, query: query )这里有一些需要注意的,首先 request.GET ,这从Django中怎样访问GET数据;POST数据通过类似的 request.POST 对象访问。这些对象行为与标准Python字典很像,在附录H中列出来其另外的特性。什么是 GET and POST 数据?GET 和POST 是浏览器使用的两个方法,用于发送数据到服务器端。一般来说,会在html表单里面看到:它指示浏览器向/books/search/以GET的方法提交数据关于GET和POST

5、这两个方法之间有很大的不同,不过我们暂时不深入它,如果你想了解更多,可以访问: http:/www.w3.org/2001/tag/doc/whenToUseGet.html 。所以下面这行:query = request.GET.get(q, )寻找名为 q 的GET参数,而且如果参数没有提交,返回一个空的字符串。注意在 request.GET 中使用了 get() 方法,这可能让大家不好理解。这里的 get() 是每个python的的字典数据类型都有的方法。使用的时候要小心:假设 request.GET 包含一个 q 的key是不安全的,所以我们使用 get(q, ) 提供一个缺省的返回值

6、 (一个空字符串)。如果只是使用 request.GETq 访问变量,在Get数据时 q 不可得,可能引发 KeyError .其次,关于 Q , Q 对象在这个例子里用于建立复杂的查询,搜索匹配查询的任何书籍.技术上 Q 对象包含QuerySet,可以在附录C中进一步阅读.在这个查询中, icontains 使用SQL的 LIKE 操作符,是大小写不敏感的。既然搜索依靠多对多域来实现,就有可能对同一本书返回多次查询结果(例如:一本书有两个作者都符合查询条件)。因此添加 .distinct() 过滤查询结果,消除重复部分。现在仍然没有这个搜索视图的模板,可以如下实现: Search% if q

7、uery % Results% endif % Search Search: % if query % Results for query|escape : % if results % % for book in results % book|escape % endfor % % else % No books found % endif % % endif %希望你已经很清楚地明白这个实现。不过,有几个细节需要指出:表单的action是 . , 表示当前的URL。这是一个标准的最佳惯常处理方式:不使用独立的视图分别来显示表单页面和结果页面;而是使用单个视图页面来处理表单并显示搜索结果。我

8、们把返回的查询值重新插入到 中去,以便于读者可以完善他们的搜索内容,而不必重新输入搜索内容。在所有使用 query 和 book 的地方,我们通过 escape 过滤器来确保任何可能的恶意的搜索文字被过滤出去,以保证不被插入到页面里。这对处理任何用户提交数据来说是 必须 的!否则的话你就开放你的网站允许跨站点脚本(XSS)攻击。在第十九章中将详细讨论了XSS和安全。不过,我们不必担心数据库对可能有危害内容的查询的处理。 Django的数据库层在这方面已经做过安全处理。【译注:数据库层对查询数据自动Escape,所以不用担心】现在我们已经作了搜索。进一步要把搜索表单加到所有的页面(例如,在bas

9、e模板);这个可以由你自己完成。下面,我们看一下更复杂的例子。事先我们讨论一个抽象的话题:完美表单。完美表单表单经常引起站点用户的反感。我们考虑一下一个假设的完美的表单的行为:它应该问用户一些信息,显然,由于可用性的问题, 使用HTML 元素和有用的上下文帮助是很重要的。所提交的数据应该多方面的验证。Web应用安全的金科玉律是从不要相信进来的数据,所以验证是必需的。如果用户有一些错误,表单应该重新显示详情,错误信息。原来的数据应该已经填好,避免用户重新录入,表单应该在所有域验证正确前一直重新显示。建立这样的表单好像需要做很多工作!幸好,Django的表单框架已经设计的可以为你做绝大部分的工作。

10、你只需要提供表单域的描述,验证规则和简单的模板即可。这样就只需要一点的工作就可以做成一个完美的表单。创建一个回馈表单做好一个网站需要注意用户的反馈,很多站点好像忘记这个。他们把联系信息放在FAQ后面,而且好像很难联系到实际的人。一个百万用户级的网站,可能有些合理的策略。如果建立一个面向用户的站点,需要鼓励回馈。我们建立一个简单的回馈表单,用来展示Django的表单框架。开始,在URLconf里添加 (rcontact/$, mysite.books.views.contact) ,然后定义表单。在Django中表单的创建类似MODEL:使用Python类来声明。这里是我们简单表单的类。为了方便

11、,把它写到新的 forms.py 文件中,这个文件在app目录下。from django import newforms as formsTOPIC_CHOICES = ( (general, General enquiry), (bug, Bug report), (suggestion, Suggestion),)class ContactForm(forms.Form): topic = forms.ChoiceField(choices=TOPIC_CHOICES) message = forms.CharField() sender = forms.EmailField(requir

12、ed=False)New Forms是什么?当Django最初推出的时候,有一个复杂而难用的form系统。用它来构建表单简直就是噩梦,所以它在新版本里面被一个叫做newforms的系统取代了。但是鉴于还有很多代码依赖于老的那个form系统,暂时Django还是同时保有两个forms包。在本书写作期间,Django的老form系统还是在 django.forms 中,新的form系统位于 django.newforms 中。这种状况迟早会改变, django.forms 会指向新的form包。但是为了让本书中的例子尽可能广泛地工作,所有的代码中仍然会使用 django.newforms 。一个D

13、jango表单是 django.newforms.Form 的子类,就像Django模型是 django.db.models.Model 的子类一样。在django.newforms模块中还包含很多Field类;Django的文档( )中包含了一个可用的Field列表。我们的 ContactForm 包含三个字段:一个topic,它是一个三选一的选择框;一个message,它是一个文本域;还有一个sender,它是一个可选的email域(因为即使是匿名反馈也是有用的)。还有很多字段类型可供选择,如果它们都不满足要求,你可以考虑自己写一个。form对象自己知道如何做一些有用的事情。它能校验数据集

14、合,生成HTML“部件”,生成一集有用的错误信息,当然,如果你确实很懒,它也能绘出整个form。现在让我们把它嵌入一个视图,看看怎么样使用它。在views.py里面:from django.db.models import Qfrom django.shortcuts import render_to_responsefrom models import Book*from forms import ContactForm*def search(request): query = request.GET.get(q, ) if query: qset = ( Q(title_icontains

15、=query) | Q(authors_first_name_icontains=query) | Q(authors_last_name_icontains=query) ) results = Book.objects.filter(qset).distinct() else: results = return render_to_response(books/search.html, results: results, query: query )*def contact(request):* *form = ContactForm()* *return render_to_respon

16、se(contact.html, form: form)*添加contact.html文件: Contact us Contact us form.as_table 最有意思的一行是 form.as_table 。form是ContactForm的一个实例,我们通过render_to_response方法把它传递给模板。as_table是form的一个方法,它把form渲染成一系列的表格行(as_ul和as_p也是起着相似的作用)。生成的HTML像这样: Topic: General enquiry Bug report Suggestion Message: Sender: 请注意:和标签并

17、没有包含在内;我们需要在模板里定义它们,这给予我们更大的控制权去决定form提交时的行为。Label元素是包含在内的,令访问性更佳(因为label的值会显示在页面上)。我们的form现在使用了一个部件来显示message字段。但我们不想限制我们的用户只能输入一行文本,所以我们用一个部件来替代:class ContactForm(forms.Form): topic = forms.ChoiceField(choices=TOPIC_CHOICES) message = forms.CharField(*widget=forms.Textarea()* ) sender = forms.Emai

18、lField(required=False)forms框架把每一个字段的显示逻辑分离到一组部件(widget)中。每一个字段类型都拥有一个默认的部件,我们也可以容易地替换掉默认的部件,或者提供一个自定义的部件。现在,提交这个form没有在后台做任何事情。让我们把我们的校验规则加进去:def contact(request): if request.method = POST: form = ContactForm(request.POST) else: form = ContactForm() return render_to_response(contact.html, form: form

19、)一个form实例可能处在两种状态:绑定或者未绑定。一个绑定的实例是由字典(或者类似于字典的对象)构造而来的,它同样也知道如何验证和重新显示它的数据。一个未绑定的form是没有与之联系的数据,仅仅知道如何显示其自身。现在可以试着提交一下这个空白的form了。页面将会被重新显示出来,显示一个验证错误,提示我们message字段是必须的。现在输入一个不合法的email地址,EmailField知道如何验证email地址,大多数情况下这种验证是合理的。设置初始数据向form的构造器函数直接传递数据会把这些数据绑定到form,指示form进行验证。我们有时也需要在初始化的时候预先填充一些字段比方说一个

20、编辑form。我们可以传入一些初始的关键字参数:form = CommentForm(initial=sender: user)如果我们的form总是会使用相同的默认值,我们可以在form自身的定义中设置它们message = forms.CharField(widget=forms.Textarea(), *initial=Replace with your feedback* )处理提交当用户填完form,完成了校验,我们需要做一些有用的事情了。在本例中,我们需要构造并发送一个包含了用户反馈的email,我们将会使用Django的email包来完成首先,我们需要知道用户数据是不是真的合法,

21、如果是这样,我们就要访问已经验证过的数据。forms框架甚至做的更多,它会把它们转换成对应的Python类型。我们的联系方式form仅仅处理字符串,但是如果我们使用IntegerField或者DataTimeField,forms框架会保证我们从中取得类型正确的值。测试一个form是否已经绑定到合法的数据,使用is_valid()方法:form = ContactForm(request.POST)if form.is_valid(): # Process form data现在我们要访问数据了。我们可以从request.POST里面直接把它们取出来,但是这样做我们就丧失了由framework

22、为我们自动做类型转换的好处了。所以我们要使用form.clean_data:if form.is_valid(): topic = form.clean_datatopic message = form.clean_datamessage sender = form.clean_data.get(sender, noreply) # .请注意因为sender不是必需的,我们为它提供了一个默认值。终于,我们要记录下用户的反馈了,最简单的方法就是把它发送给站点管理员,我们可以使用send_mail方法:from django.core.mail import send_mail# .send_ma

23、il( Feedback from your site, topic: %s % topic, message, sender, administrator)send_mail方法有四个必须的参数:主题,邮件正文,from和一个接受者列表。send_mail是Django的EmailMessage类的一个方便的包装,EmailMessage类提供了更高级的方法,比如附件,多部分邮件,以及对于邮件头部的完整控制。 发送完邮件之后,我们会把用户重定向到确认的页面。完成之后的视图方法如下:发送完邮件之后,我们会把用户重定向到确认的页面。完成之后的视图方法如下:from django.http imp

24、ort HttpResponseRedirectfrom django.shortcuts import render_to_responsefrom django.core.mail import send_mailfrom forms import ContactFormdef contact(request): if request.method = POST: form = ContactForm(request.POST) if form.is_valid(): topic = form.clean_datatopic message = form.clean_datamessage

25、 sender = form.clean_data.get(sender, noreply) send_mail( Feedback from your site, topic: %s % topic, message, sender, administrator ) return HttpResponseRedirect(/contact/thanks/) else: form = ContactForm() return render_to_response(contact.html, form: form)在POST之后立即重定向在一个POST请求过后,如果用户选择刷新页面,这个请求就重

26、复提交了。这常常会导致我们不希望的行为,比如重复的数据库记录。在POST之后重定向页面是一个有用的模式,可以避免这样的情况出现:在一个POST请求成功的处理之后,把用户导引到另外一个页面上去,而不是直接返回HTML页面。自定义校验规则假设我们已经发布了反馈页面了,email已经开始源源不断地涌入了。只有一个问题:一些email只有寥寥数语,很难从中得到什么详细有用的信息。所以我们决定增加一条新的校验:来点专业精神,最起码写四个字,拜托。我们有很多的方法把我们的自定义校验挂在Django的form上。如果我们的规则会被一次又一次的使用,我们可以创建一个自定义的字段类型。大多数的自定义校验都是一次

27、性的,可以直接绑定到form类.我们希望message字段有一个额外的校验,我们增加一个clean_message方法:class ContactForm(forms.Form): topic = forms.ChoiceField(choices=TOPIC_CHOICES) message = forms.CharField(widget=forms.Textarea() sender = forms.EmailField(required=False) def clean_message(self): message = self.clean_data.get(message, ) num_words = len(

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1