ID English原文 中文翻译 最近翻译记录 状态 操作
Chapter 7: Form Processing
第七章  表单处理

5798天前 ZAP 翻译
**Guest author: Simon Willison**
**本章作者是Simon Willison**

5798天前 ZAP 翻译
After following along with the last chapter, you should now have a fully
functioning if somewhat simple site. In this chapter, well deal with the next
piece of the puzzle: building views that take input from readers.
5796天前 ZAP 翻译
Well start by making a simple search form by hand and looking at how to handle
data submitted from the browser. From there, well move on to using Djangos
forms framework.
5783天前 ZAP 翻译

5798天前 ZAP 翻译
The Web is all about search. Two of the Nets biggest success stories, Google
and Yahoo, built their multi-billion-dollar businesses around search. Nearly
every site sees a large percentage of traffic coming to and from its search
pages. Often the difference between the success or failure of a site is the
quality of its search. So it looks like wed better add some searching to our
fledgling books site, no?
5795天前 ZAP 翻译
Well start by adding the search view to our URLconf (``mysite.urls`` ). Recall
that this means adding something like ``(r'^search/$',
'')`` to the set of URL patterns.
开始,在URLconf (``mysite.urls`` )添加搜索视图。添加类似
``(r'^search/$','')`` 设置URL模式。
5772天前 ZAP 翻译
Next, well write this ``search`` view into our view module
(``mysite.books.views`` ):
下一步,在视图模块(``mysite.books.views`` )中写这个 ``search`` 视图:
5772天前 翻译
There are a couple of things going on here that you havent yet seen. First,
theres ``request.GET`` . This is how you access GET data from Django; POST data
is accessed through a similar ``request.POST`` object. These objects behave
exactly like standard Python dictionaries with some extra features covered in
Appendix H.
这里有一些需要注意的,首先 ``request.GET`` ,这是如何从Django中访问GET数据;POST数据通过类似的 ``request.POST`` 对象访问。这些对象行为与标准Python字典很像,在附录H中列出来其另外的特性。
3383天前 翻译
Whats GET and POST Data?
什么是 GET and POST 数据?
5795天前 翻译
GET and POST are the two methods that browsers use to send data to a server.
Most of the time, youll see them in HTML form tags:
GET 和POST 是浏览器使用的两个方法,用于发送数据到服务器端。
5795天前 翻译
This instructs the browser to submit the form data to the URL
``/books/search/`` using the GET method.
5794天前 翻译
There are important differences between the semantics of GET and POST that we
wont get into right now, but see
``_ if you want to learn more.
关于GET和POST这两个方法之间有很大的不同,不过我们暂时不深入它,如果你想了解更多,可以访问: ``_ 。
5512天前 翻译
So the line:
5793天前 翻译
looks for a GET parameter named ``q`` and returns an empty string if that
parameter wasnt submitted.
寻找名为 ``q`` 的GET参数,而且如果参数没有提交,返回一个空的字符串。
5716天前 翻译
Note that were using the ``get()`` method on ``request.GET`` , which is
potentially confusing. The ``get()`` method here is the one that every Python
dictionary has. Were using it here to be careful: it is *not* safe to assume
that ``request.GET`` contains a ``'q'`` key, so we use ``get('q', '')`` to
provide a default fallback value of ``''`` (the empty string). If we merely
accessed the variable using ``request.GET['q']`` , that code would raise a
``KeyError`` if ``q`` wasnt available in the GET data.
注意在 ``request.GET`` 中使用了 ``get()`` 方法,这可能让大家不好理解。这里的 ``get()`` 是每个python的的字典数据类型都有的方法。使用的时候要小心:假设 ``request.GET`` 包含一个 ``'q'`` 的key是不安全的,所以我们使用 ``get('q', '')`` 提供一个缺省的返回值 ``''`` (一个空字符串)。如果只是使用 ``request.GET['q']`` 访问变量,在Get数据时 ``q`` 不可得,可能引发 ``KeyError`` .
5593天前 翻译
Second, what about this ``Q`` business? ``Q`` objects are used to build up
complex queries in this case, were searching for any books where either the
title or the name of one of the authors matches the search query. Technically,
these ``Q`` objects comprise a QuerySet, and you can read more about them in
Appendix C.
其次,关于 ``Q`` , ``Q`` 对象在这个例子里用于建立复杂的查询,搜索匹配查询的任何书籍.技术上 ``Q`` 对象包含QuerySet,可以在附录C中进一步阅读.
5716天前 Chamomile 翻译
In these queries, ``icontains`` is a case-insensitive search that uses the SQL
``LIKE`` operator in the underlying database.
在这个查询中, ``icontains`` 使用SQL的 ``LIKE`` 操作符,是大小写不敏感的。
5716天前 翻译
Since were searching against a many-to-many field, its possible for the same
book to be returned more than once by the query (e.g., a book with two authors
who both match the search query). Adding ``.distinct()`` to the filter lookup
eliminates any duplicate results.
既然搜索依靠多对多域来实现,就有可能对同一本书返回多次查询结果(例如:一本书有两个作者都符合查询条件)。因此添加 ``.distinct()``  过滤查询结果,消除重复部分。
5716天前 翻译
Theres still no template for this search view, however. This should do the
5793天前 翻译
Hopefully by now what this does is fairly obvious. However, there are a few
subtleties worth pointing out:
5771天前 翻译
    The forms action is ``.`` , which means the current URL. This is a standard
    best practice: dont use separate views for the form page and the results
    page; use a single one that serves the form and search results.
    表单的action是 ``.`` , 表示当前的URL。这是一个标准的最佳惯常处理方式:不使用独立
5567天前 翻译
    We reinsert the value of the query back into the ``<input>`` . This lets
    readers easily refine their searches without having to retype what they
    searched for.
    我们把返回的查询值重新插入到 ``<input>`` 中去,以便于读者可以完善他们的搜索内容,
5716天前 翻译
    Everywhere ``query`` and ``book`` is used, we pass it through the
    ``escape`` filter to make sure that any potentially malicious search text
    is filtered out before being inserted into the page.
    在所有使用 ``query`` 和 ``book`` 的地方,我们通过 ``escape`` 过滤器来确保任何
5772天前 翻译
    Its *vital* that you do this with any user-submitted content! Otherwise you
    open your site up to cross-site scripting (XSS) attacks. Chapter 19
    discusses XSS and security in more detail.
    这对处理任何用户提交数据来说是 *必须* 的!否则的话你就开放你的网站允许跨站点脚本
5772天前 翻译
    However, we dont need to worry about harmful content in your database
    lookups we can simply pass the query into the lookup as is. This is because
    Djangos database layer handles this aspect of security for you.
5772天前 翻译
Now we have a working search. A further improvement would be putting a search
form on every page (i.e., in the base template); well let you handle that one
5793天前 Tisha 翻译
Next, well look at a more complex example. But before we do, lets discuss a
more abstract topic: the perfect form.
5793天前 翻译
The Perfect Form
5793天前 翻译
Forms can often be a major cause of frustration for the users of your site.
Lets consider the behavior of a hypothetical perfect form:
5793天前 翻译
*   It should ask the user for some information, obviously. Accessibility and
    usability matter here, so smart use of the HTML ``<label>`` element and
    useful contextual help are important.
*   它应该问用户一些信息,显然,由于可用性的问题, 使用HTML ``<label>`` 元素和有用的
5746天前 翻译
*   The submitted data should be subjected to extensive validation. The golden
    rule of Web application security is never trust incoming data, so
    validation is essential.
*   所提交的数据应该多方面的验证。Web应用安全的金科玉律是从不要相信进来的数据,所以验证是必需的。

5793天前 翻译
*   If the user has made any mistakes, the form should be redisplayed with
    detailed, informative error messages. The original data should be
    prefilled, to save the user from having to reenter everything.
*   如果用户有一些错误,表单应该重新显示详情,错误信息。原来的数据应该已经填好,避免用户重新录入,
5793天前 翻译
*   The form should continue to redisplay until all of the fields have been
    correctly filled.
*   表单应该在所有域验证正确前一直重新显示。
5793天前 翻译
Constructing the perfect form seems like a lot of work! Thankfully, Djangos
forms framework is designed to do most of the work for you. You provide a
description of the forms fields, validation rules, and a simple template, and
Django does the rest. The result is a perfect form with very little effort.
5793天前 翻译
Creating a Feedback Form
5793天前 翻译
The best way to build a site that people love is to listen to their feedback.
Many sites appear to have forgotten this; they hide their contact details
behind layers of FAQs, and they seem to make it as difficult as possible to get
in touch with an actual human being.
5772天前 翻译
When your site has millions of users, this may be a reasonable strategy. When
youre trying to build up an audience, though, you should actively encourage
feedback at every opportunity. Lets build a simple feedback form and use it to
illustrate Djangos forms framework in action.
5793天前 翻译
Well start by adding adding ``(r'^contact/$', '')``
to the URLconf, then defining our form. Forms in Django are created in a
similar way to models: declaratively, using a Python class. Heres the class for
our simple form. By convention, well insert it into a new ```` file
within our application directory:
开始,在URLconf里添加 ``(r'^contact/$', '')`` ,然后定义表单。
在Django中表单的创建类似MODEL:使用Python类来声明。这里是我们简单表单的类。为了方便,把它写到新的 ```` 文件中,这个文件在app目录下。
5594天前 翻译
New Forms? What?
New Forms是什么?
5793天前 翻译
When Django was first released to the public, it had a complicated, confusing
forms system. It made producing forms far too difficult, so it was completely
rewritten and is now called newforms. However, theres still a fair amount of
code that depends on the old form system, so for the time being Django ships
with two form packages.
5783天前 翻译
As we write this book, Djangos old form system is still available as
``django.forms`` and the new form package as ``django.newforms`` . At some
point that will change and ``django.forms`` will point to the new form package.
However, to make sure the examples in this book work as widely as possible, all
the examples will refer to ``django.newforms`` .
在本书写作期间,Django的老form系统还是在 ``django.forms`` 中,新的form系统位于
``django.newforms`` 中。这种状况迟早会改变, ``django.forms`` 会指向新的form包。
但是为了让本书中的例子尽可能广泛地工作,所有的代码中仍然会使用 ``django.newforms`` 。 
5772天前 翻译
A Django form is a subclass of ``django.newforms.Form`` , just as a Django
model is a subclass of ``django.db.models.Model`` . The ``django.newforms``
module also contains a number of ``Field`` classes; a full list is available in
Djangos documentation at
一个Django表单是 ``django.newforms.Form`` 的子类,就像Django模型是 ``django.db.models.Model`` 的子类一样。在django.newforms模块中还包含很多Field类;Django的文档( ``_ )中包含了一个可用的Field列表。 
5771天前 翻译
Our ``ContactForm`` consists of three fields: a topic, which is a choice among
three options; a message, which is a character field; and a sender, which is an
email field and is optional (because even anonymous feedback can be useful).
There are a number of other field types available, and you can write your own
if they dont cover your needs.
我们的 ``ContactForm`` 包含三个字段:一个topic,它是一个三选一的选择框;一个message,它是一个文本域;还有一个sender,它是一个可选的email域(因为即使是匿名反馈也是有用的)。还有很多字段类型可供选择,如果它们都不满足要求,你可以考虑自己写一个。 
5518天前 翻译
The form object itself knows how to do a number of useful things. It can
validate a collection of data, it can generate its own HTML widgets, it can
construct a set of useful error messages and, if were feeling lazy, it can even
draw the entire form for us. Lets hook it into a view and see it in action. In
```` :
5783天前 翻译
and in ``contact.html`` :
5770天前 翻译
The most interesting line here is ``{{ form.as_table }}`` . ``form`` is our
ContactForm instance, as passed to ``render_to_response`` . ``as_table`` is a
method on that object that renders the form as a sequence of table rows
(``as_ul`` and ``as_p`` can also be used). The generated HTML looks like this:
最有意思的一行是 {{ form.as_table }}。form是ContactForm的一个实例,我们通过render_to_response方法把它传递给模板。as_table是form的一个方法,它把form渲染成一系列的表格行(as_ul和as_p也是起着相似的作用)。生成的HTML像这样: 
5783天前 翻译
Note that the ``<table>`` and ``<form>`` tags are not included; you need to
define those yourself in the template, which gives you control over how the
form behaves when it is submitted. Label elements *are* included, making forms
accessible out of the box.
5783天前 翻译
Our form is currently using a ``<input type="text">`` widget for the message
field. We dont want to restrict our users to a single line of text, so well
swap in a ``<textarea>`` widget instead:
我们的form现在使用了一个<input type="text">部件来显示message字段。但我们不想限制我们的用户只能输入一行文本,所以我们用一个<textarea>部件来替代: 
5783天前 翻译
The forms framework separates out the presentation logic for each field into a
set of widgets. Each field type has a default widget, but you can easily
override the default, or provide a custom widget of your own.
5783天前 翻译
At the moment, submitting the form doesnt actually do anything. Lets hook in
our validation rules:
5783天前 翻译
A form instance can be in one of two states: bound or unbound. A *bound*
instance is constructed with a dictionary (or dictionary-like object) and knows
how to validate and redisplay the data from it. An *unbound* form has no data
associated with it and simply knows how to display itself.
5783天前 翻译
Try clicking Submit on the blank form. The page should redisplay, showing a
validation error that informs us that our message field is required.
5783天前 翻译
Try entering an invalid email address as well. The ``EmailField`` knows how to
validate email addresses, at least to a reasonable level of doubt.
5783天前 翻译
Setting Initial Data
5783天前 翻译
Passing data directly to the form constructor binds that data and indicates
that validation should be performed. Often, though, we need to display an
initial form with some of the fields prefilled for example, an edit form. We
can do this with the ``initial`` keyword argument:
5783天前 翻译
If our form will *always* use the same default values, we can configure them in
the form definition itself:
5783天前 翻译
Processing the Submission
5783天前 翻译
Once the user has filled the form to the point that it passes our validation
rules, we need to do something useful with the data. In this case, we want to
construct and send an email containing the users feedback. Well use Djangos
email package to do this.
5783天前 Brooks 翻译
First, though, we need to tell if the data is indeed valid, and if it is, we
need access to the validated data. The forms framework does more than just
validate the data, it also converts it into Python types. Our contact form only
deals with strings, but if we were to use an ``IntegerField`` or
``DateTimeField`` , the forms framework would ensure that we got back a Python
integer or ``datetime`` object, respectively.
5783天前 翻译
To tell whether a form is bound to valid data, call the ``is_valid()`` method:
5783天前 翻译
Now we need access to the data. We could pull it straight out of
``request.POST`` , but if we did, wed miss out on the type conversions
performed by the forms framework. Instead, we use ``form.clean_data`` :
5628天前 翻译
Note that since ``sender`` is not required, we provide a default when its
missing. Finally, we need to record the users feedback. The easiest way to do
this is to email it to a site administrator. We can do that using the
``send_mail`` function:
5783天前 翻译
The ``send_mail`` function has four required arguments: the email subject, the
email body, the from address, and a list of recipient addresses. ``send_mail``
is a convenient wrapper around Djangos ``EmailMessage`` class, which provides
advanced features such as attachments, multipart emails, and full control over
email headers.
send_mail方法有四个必须的参数:主题,邮件正文,from和一个接受者列表。send_mail是Django的EmailMessage类的一个方便的包装,EmailMessage类提供了更高级的方法,比如附件,多部分邮件,以及对于邮件头部的完整控制。 发送完邮件之后,我们会把用户重定向到确认的页面。完成之后的视图方法如下:
5783天前 翻译
Having sent the feedback email, well redirect our user to a static confirmation
page. The finished view function looks like this:
5783天前 翻译
Redirect After POST
5783天前 翻译
If a user selects Refresh on a page that was displayed by a POST request, that
request will be repeated. This can often lead to undesired behavior, such as a
duplicate record being added to the database. Redirect after POST is a useful
pattern that can help avoid this scenario: after a successful POST has been
processed, redirect the user to another page rather than returning HTML
5783天前 翻译
Custom Validation Rules
1d0p2u  <a href="">azetemwaeinp</a>, [url=]lcaytpsbsxkh[/url], [link=]hgjnhjgnqlch[/link],
4383天前 翻译
Imagine weve launched our feedback form, and the emails have started tumbling
in. Theres just one problem: some of the emails are just one or two words,
hardly enough for a detailed missive. We decide to adopt a new validation
policy: four words or more, please.
5783天前 翻译
There are a number of ways to hook custom validation into a Django form. If our
rule is something we will reuse again and again, we can create a custom field
type. Most custom validations are one-off affairs, though, and can be tied
directly to the form class.
5783天前 翻译
We want additional validation on the ``message`` field, so we need to add a
``clean_message`` method to our form:
5783天前 翻译
This new method will be called after the default field validator (in this case,
the validator for a required ``CharField`` ). Because the field data has
already been partially processed, we need to pull it out of the forms
``clean_data`` dictionary.
5783天前 翻译
We naively use a combination of ``len()`` and ``split()`` to count the number
of words. If the user has entered too few words, we raise a ``ValidationError``
. The string attached to this exception will be displayed to the user as an
item in the error list.
5783天前 翻译
It is important that we explicitly return the value for the field at the end of
the method. This allows us to modify the value (or convert it to a different
Python type) within our custom validation method. If we forget the return
statement, then ``None`` will be returned, and the original value will be lost.
5783天前 翻译
A Custom Look and Feel
5767天前 翻译
The quickest way to customize the forms presentation is with CSS. The list of
errors in particular could do with some visual enhancement, and the ``<ul>``
has a class attribute of ``errorlist`` for that exact purpose. The following
CSS really makes our errors stand out:
5783天前 翻译
While its convenient to have our forms HTML generated for us, in many cases the
default rendering wont be right for our application. ``{{ form.as_table }}``
and friends are useful shortcuts while we develop our application, but
everything about the way a form is displayed can be overridden, mostly within
the template itself.
5783天前 翻译
Each field widget (``<input type="text">`` , ``<select>`` , ``<textarea>`` , or
similar) can be rendered individually by accessing ``{{ form.fieldname }}`` .
Any errors associated with a field are available as ``{{ form.fieldname.errors
}}`` . We can use these form variables to construct a custom template for our
contact form:
每一个字段部件(<input type="text">, <select>, <textarea>, 或者类似)都可以通过访问{{form.字段名}}进行单独的渲染。任何跟字段相关的错误都可以通过{{form.fieldname.errors}}访问。我们可以同这些form的变量来为我们的表单构造一个自定义的模板:
5783天前 翻译
``{{ form.message.errors }}`` will display as a ``<ul class="errorlist">`` if
errors are present and a blank string if the field is valid (or the form is
unbound). We can also treat ``form.message.errors`` as a Boolean or even
iterate over it as a list, for example:
``{{ form.message.errors }}`` 会在 ``<ul class="errorlist">`` 里面显示,如果字段是合法的,或者form没有被绑定,就显示一个空字符串。我们还可以把 ``form.message.errors`` 当作一个布尔值或者当它是list在上面做迭代:
5716天前 翻译
In the case of validation errors, this will add an errors class to the
containing ``<div>`` and display the list of errors in an ordered list.
在校验失败的情况下, 这段代码会在包含错误字段的div的class属性中增加一个"errors",在一个有序列表中显示错误信息。
5783天前 翻译
Creating Forms from Models
5767天前 翻译
Lets build something a little more interesting: a form that submits a new
publisher to our book application from Chapter 5.
5783天前 翻译
An important rule of thumb in software development that Django tries to adhere
to is Dont Repeat Yourself (DRY). Andy Hunt and Dave Thomas in *The Pragmatic
Programmer* define this as follows:
一个非常重要的Django的开发理念就是不要重复你自己(DRY)。Any Hunt和Dave Thomas在《实用主义程序员》里定义了这个原则:
5783天前 翻译
Every piece of knowledge must have a single, unambiguous, authoritative
representation within a system.
5783天前 翻译
Our ``Publisher`` model class says that a publisher has a name, address, city,
state_province, country, and website. Duplicating this information in a form
definition would break the DRY rule. Instead, we can use a useful shortcut:
``form_for_model()`` :
5783天前 翻译
``PublisherForm`` is a ``Form`` subclass, just like the ``ContactForm`` class
we created manually earlier on. We can use it in much the same way:
5783天前 翻译
The ``add_publisher.html`` file is almost identical to our original
``contact.html`` template, so it has been omitted. Also remember to add a new
pattern to the URLconf: ``(r'^add_publisher/$',
'mysite.books.views.add_publisher')`` .
``add_publisher.html`` 文件几乎跟我们的contact.html模板一样,所以不赘述了。记得在URLConf里面加上: ``(r'^add_publisher/$', 'mysite.books.views.add_publisher')`` . 
5567天前 翻译
Theres one more shortcut being demonstrated here. Since forms derived from
models are often used to save new instances of the model to the database, the
form class created by ``form_for_model`` includes a convenient ``save()``
method. This deals with the common case; youre welcome to ignore it if you want
to do something a bit more involved with the submitted data.
还有一个快捷的方法。因为从模型而来的表单经常被用来把新的模型的实例保存到数据库,从 ``form_for_model`` 而来的表单对象包含一个 ``save()`` 方法。一般情况下够用了;你想对提交的数据作进一步的处理的话,无视它就好了。
5567天前 翻译
``form_for_instance()`` is a related method that can create a preinitialized
form from an instance of a model class. This is useful for creating edit forms.
``form_for_instance()`` 是另外一个方法,用于从一个模型对象中产生一个初始化过的表单对象,这个当然给“编辑”表单提供了方便。
4271天前 翻译
Whats Next?
5716天前 翻译
This chapter concludes the introductory material in this book. The next 13
chapters deal with various advanced topics, including generating content other
than HTML (Chapter 11), security (Chapter 19), and deployment (Chapter 20).
5567天前 翻译
After these first seven chapters, you should know enough to start writing your
own Django projects. The rest of the material in this book will help fill in
the missing pieces as you need them.
5783天前 翻译
Well start in Chapter 8 by doubling back and taking a closer look at views and
URLconfs (introduced first in Chapter 3).
5783天前 翻译