1.从Request对象中获取数据

    每个view函数的第一个参数是一个HttpRequest对象,在view函数的执行过程中,你可以用这些属性来获取当前request的一些信息(比如,你正在加载这个页面的用户是谁,或者用的是什么浏览器)。

HttpRequest对象包含当前请求URL的一些信息:

属性/方法                 说明                                 举例 

request.path       除域名以外的请求路径,以正斜杠开头 "/hello/" 

request.get_host() 主机名(比如,通常所说的域名) "127.0.0.1:8000" or "www.example.com" 

request.get_full_path() 请求路径,可能包含查询字符串 "/hello/?print=true" 

request.is_secure() 如果通过HTTPS访问,则此方法返回True,否则返回False   True或者False

2.有关request的其它信息

    request.META 是一个Python字典,包含了所有本次HTTP请求的Header信息,比如用户IP地址和用户Agent(通常是浏览器的名称和版本号)。这个字典中几个常见的键值有:

HTTP_REFERER 进站前链接网页,如果有的话。 (请注意,它是REFERRER的笔误。)

HTTP_USER_AGENT 用户浏览器的user-agent字符串,如果有的话。 例如: "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.8.1.17) Gecko/20080829 Firefox/2.0.0.17" .

REMOTE_ADDR 客户端IP,如:"12.345.67.89" 。(如果申请是经过代理服务器的话,那么它可能是以逗号分割的多个IP地址,如:"12.345.67.89,23.456.78.90" 。)

3.提交数据信息

    除了基本的元数据,HttpRequest对象还有两个属性包含了用户所提交的信息: request.GET 和 request.POST。二者都是类字典对象,你可以通过它们来访问GET和POST数据。

    获取使用POST方法的数据与GET的相似,只是使用request.POST代替了request.GET。那么,POST与GET之间有什么不同?当我们提交表单仅仅需要获取数据时就可以用GET; 而当我们提交表单时需要更改服务器数据的状态,或者说发送e-mail,或者其他不仅仅是获取并显示数据的时候就使用POST。

4.一个简单的表单处理示例

    通常,表单开发分为两个部分: 前端HTML页面用户接口和后台view函数对所提交数据的处理过程。

# urls.py

urlpatterns = patterns('',
    # ...
    (r'^search-form/$', views.search_form),
    (r'^search/$', views.search),
    # ...
)

# views.py

def search_form(request):
    return render_to_response('search_form.html')

def search(request):
    if 'q' in request.GET:
        message = 'You searched for: %r' % request.GET['q']
    else:
        message = 'You submitted an empty form.'
    return HttpResponse(message)
    
# search_form.html

<html>
<head>
    <title>Search</title>
</head>
<body>
    <form action="/search/" method="get">
        <input type="text" name="q">
        <input type="submit" value="Search">
    </form>
</body>
</html>

1).在HTML里我们定义了一个变量q。当提交表单时,变量q的值通过GET(method=”get”)附加在URL /search/上。

2).处理/search/(search())的视图通过request.GET来获取q的值。

5.From类

    Django带有一个form库,称为django.forms,这个库可以处理我们本章所提到的包括HTML表单显示以及验证。

    表单框架最主要的用法是,为每一个将要处理的HTML的 <Form> 定义一个Form类。在这个例子中,我们只有一个 <Form> ,因此我们只需定义一个Form类。 这个类可以存在于任何地方,甚至直接写在 views.py 文件里也行,但通常惯例是把Form类都放到一个文件中:forms.py。例如:

from django import forms

class ContactForm(forms.Form):
    subject = forms.CharField()
    email = forms.EmailField(required=False)
    message = forms.CharField()

form对象执行过程:

它做的第一件事是将自己显示成HTML:

>>> from contact.forms import ContactForm
>>> f = ContactForm()
>>> print f
<tr><th><label for="id_subject">Subject:</label></th><td><input type="text" name="subject" id="id_subject" /></td></tr>
<tr><th><label for="id_email">Email:</label></th><td><input type="text" name="email" id="id_email" /></td></tr>
<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" /></td></tr>

Form对象做的第二件事是校验数据。为了校验数据,我们创建一个新的对Form象,并且传入一个与定义匹配的字典类型数据。一旦你对一个Form实体赋值,你就得到了一个绑定form:

>>> f = ContactForm({'subject': 'Hello', 'email': 'adrian@example.com', 'message': 'Nice site!'})
>>> f.is_bound
True
>>> f.is_valid()
True

每一个邦定Form实体都有一个errors属性,它为你提供了一个字段与错误消息相映射的字典表。

>>> f = ContactForm({'subject': 'Hello', 'message': ''})
>>> f.errors
{'message': [u'This field is required.']}

最终,如果一个Form实体的数据是合法的,它就会有一个可用的cleaned_data属性。 这是一个包含干净的提交数据的字典。 Django的form框架不但校验数据,它还会把它们转换成相应的Python类型数据,这叫做清理数据。

>>> f = ContactForm({subject': Hello, email: adrian@example.com, message: Nice site!})
>>> f.is_valid()
True
>>> f.cleaned_data
{message': uNice site!, email: uadrian@example.com, subject: uHello}

自定义校验规则:

我们希望 message 字段有一个额外的校验,我们增加一个 clean_message() 方法到 Form 类:

from django import forms

class ContactForm(forms.Form):
    subject = forms.CharField(max_length=100)
    email = forms.EmailField(required=False)
    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

Django的form系统自动寻找匹配的函数方法,该方法名称以clean_开头,并以字段名称结束。 如果有这样的方法,它将在校验时被调用。

注:clean_message()方法将在指定字段的默认校验逻辑执行之后被调用。(本例中,在必填CharField这个校验逻辑之后。)因为字段数据已经被部分处理,所以它被从self.cleaned_data中提取出来了。同样,我们不必担心数据是否为空,因为它已经被校验过了。