URL 相关信息
equest.path 除域名 以外的请求路径, 以正斜杠开头 eg.”/hello/”
request.get_host() 主 机名( 比如, 通常所说的域名) eg.”127.0.0.1:8000″ or “www.example.com”
request.get_full_path() 请求路径, 可能包含查 询字符串
eg.request.is_secure() “/hello/?print=true”
如果通过HTTPS 访问, 则此方法返回True, 否则返回False eg.True 或者 False
有关request 的 其它信息
- 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″ 。)
# GOOD (VERSION 1)
def ua_display_good1(request):
try:
ua = request.META['HTTP_USER_AGENT']
except KeyError:
ua = ‘unknown’
return HttpResponse(“Your browser is %s” % ua)
# GOOD (VERSION 2)
def ua_display_good2(request):
ua = request.META.get(‘HTTP_USER_AGENT’, ‘unknown’)
return HttpResponse(“Your browser is %s” % ua)
提交的数据信息
request.GET 和request.POST 。二者都是类字典对象, 你可以通过它们来访问GET 和POST 数据。
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)
通过数据库进行查询
from django.http import HttpResponse
from django.shortcuts import render_to_response
from mysite.books.models import Book
def search(request):
if ‘q’ in request.GET and request.GET['q']:
q = request.GET['q']
books = Book.objects.filter(title__icontains=q)
return render_to_response(’search_results.html’, {‘books’: books, ‘query’: q})
else:
return HttpResponse(‘Please submit a search term.’)
返回到模板中
<p>You searched for: <strong>{{ query }}</strong></p>
{% if books %}
<p>Found {{ books|length }} book{{ books|pluralize }}.</p>
<ul>
{% for book in books %}
<li>{{ book.title }}</li>
{% endfor %}
</ul>
{% else %}
<p>No books matched your search criteria.</p>
{% endif %}
简单的验证
def search(request):
errors = []
if ‘q’ in request.GET:
q = request.GET['q']
if not q:
errors.append(‘Enter a search term.’)**
elif len(q) > 20:
errors.append(‘Please enter at most 20 characters.’)**
else:
books = Book.objects.filter(title__icontains=q)
return render_to_response(’search_results.html’, {‘books’: books, ‘query’: q})
return render_to_response(’search_form.html’, {**’errors’: errors** })
<html>
<head>
<title>Search</title>
</head>
<body>
**{% if errors %}**
**<ul>**
**{% for error in errors %}**
**<li>{{ error }}</li>**
**{% endfor %}**
**</ul>**
**{% endif %}**
<form action=”/search/” method=”get”>
<input type=”text” name=”q”>
<input type=”submit” value=”Search”>
</form>
</body>
</html>
第一个Form 类
Django 带有一个form 库, 称为django.forms, 这个库可以处理我们本章 所提到的包括HTML 表单显示以及验 证。 接下来我们来深入了解一下form 库, 并使用她来重写contact 表单应用。
forms.py 。在存放“ views.py“ 的目录中, 创建这个文件, 然后输入:
from django import forms
class ContactForm(forms.Form):
subject = forms.CharField()
email = forms.EmailField(required=False)
message = forms.CharField()
这看上去简单易懂, 并且很像在模 块中使用的语法。 表单中的每一个字段( 域) 作为Form 类的属性, 被展现成Field 类。这里只用到CharField 和EmailField 类型。 每一个字段都默认是必填。要使email 成 为可选项, 我们需要指定required=False 。
让我们钻研到Python 解释器 里面看看这个类做了些什么。 它做的第一件事是将自己显示成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_
<tr><th><label for=”id_email”>Email:</label></th><td><input type=”text” name=”email” id=”id_email”
<tr><th><label for=”id_message”>Message:</label></th><td><input type=”text” name=”message” id=”id_
为了便于访问,Django 用“ <label>“ 标志, 为每一个字段添加了标签。 这个做法使默认行为尽可能合适。
默认输出按照HTML 的<“ table“ > 格式, 另外有一些其它格式的输出:
>>> print f.as_ul()
<li><label for=”id_subject”>Subject:</label> <input type=”text” name=”subject” id=”id_subject” /><
<li><label for=”id_email”>Email:</label> <input type=”text” name=”email” id=”id_email” /></li>
<li><label for=”id_message”>Message:</label> <input type=”text” name=”message” id=”id_message” /><
>>> print f.as_p()
<p><label for=”id_subject”>Subject:</label> <input type=”text” name=”subject” id=”id_subject” /></
<p><label for=”id_email”>Email:</label> <input type=”text” name=”email” id=”id_email” /></p>
<p><label for=”id_message”>Message:</label> <input type=”text” name=”message” id=”id_message” /></
请注意, 标签<table> 、<ul> 、<form> 的开闭合标记没有包含于输 出当中, 这样你就可以添加额外的行或者 自定义格式。
这些类方法只是一般情况下用于快捷显示完整表单的方法。 你同样可以用HTML 显示个别字段:
>>> print f['subject']
<input type=”text” name=”subject” id=”id_subject” />
>>> print f['message']
<input type=”text” name=”message” id=”id_message” />
Form 对象做的第二件事是校 验数据。 为了校验数据, 我们创建一个 新的对Form 象, 并且传入一个与定义匹配的字典类型数据:
>>> f = ContactForm({’subject’: ‘Hello’, ‘email’: ‘adrian@example.com’, ‘message’: ‘Nice site!’})
一旦你对一个Form 实体赋值, 你就得到了一个绑定form:
>>> f.is_bound
True
调用任何绑定form 的is_valid() 方法, 就可以知道它的数据是否合法。 我们已经为每个字段传入了值, 因此整个Form 是合法的:
>>> f.is_valid()
True
如果我们不传入email 值, 它依然是合法的。因为我们指定这个字段的属性required=False:
>>> f = ContactForm({’subject’: ‘Hello’, ‘message’: ‘Nice site!’})
>>> f.is_valid()
True
但是, 如果留空subject 或message , 整个Form 就不再合法了:
>>> f = ContactForm({’subject’: ‘Hello’})
>>> f.is_valid()
False
>>> f = ContactForm({’subject’: ‘Hello’, ‘message’: ”})
>>> f.is_valid()
False
你可以逐一查看每个字段的出错消息:
>>> f = ContactForm({’subject’: ‘Hello’, ‘message’: ”})
>>> f['message'].errors
[u'This field is required.']
>>> f['subject'].errors
[]
>>> f['email'].errors
[]
每一个邦定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}
我们的contact form 只 涉及字符串类型, 它们会被清理成Unicode 对象。如果我们使用整数型或日期型,form 框架会确保方法使用合适的Python 整数型或datetime.date 型对象。
在视图中使用Form 对 象
# views.py
from django.shortcuts import render_to_response
from mysite.contact.forms import ContactForm
def contact(request):
if request.method == ‘POST’:
form = ContactForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
send_mail(
cd['subject'],
cd['message'],
cd.get(‘email’, ‘noreply@example.com’),
['siteowner@example.com'],
)
return HttpResponseRedirect(‘/contact/thanks/’)
else:
form = ContactForm()
return render_to_response(‘contact_form.html’, {‘form’: form})
# contact_form.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”>
<table>
{{ form.as_table }}
</table>
<input type=”submit” value=”Submit”>
</form>
</body>
</html>
改变字段显示
你可能首先注意到: 当你在本地显 示这个表单的时,message 字段 被显示成“ input type=”text”“ , 而 它应该被显示成<“ textarea“ > 。我们可以通过设置* widget* 来修改它:
from django import forms
class ContactForm(forms.Form):
subject = forms.CharField()
email = forms.EmailField(required=False)
message = forms.CharField(**widget=forms.Textarea** )
forms 框架把每一个字段的显 示逻辑分离到一组部件(widget) 中。 每一个字段类型都拥有一个默认的部件, 我 们也可以容易地替换掉默认的部件, 或者 提供一个自定义的部件。
设置最大长度
一个最经常使用的校验要求是检 查字段长度。 另外, 我们应该改进ContactForm, 使subject 限制在100 个字符
以内。 为此, 仅需为CharField 提供max_length 参数, 像这样:
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)
选项min_length 参数 同样可用。
设置初始值
让我们再改进一下这个表单: 为字subject 段添加* 初始值* : “I love your site!” ( 一 点建议, 但没坏
处。) 为此, 我们可以在创建Form 实体时, 使用initial 参数:
def contact(request):
if request.method == ‘POST’:
form = ContactForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
send_mail(
cd['subject'],
cd['message'],
cd.get(‘email’, `’noreply@example.com`_’),
[`'siteowner@example.com`_'],
)
return HttpResponseRedirect(‘/contact/thanks/’)
else:
form = ContactForm(
**initial={’subject’: ‘I love your site!’}**
)
return render_to_response(‘contact_form.html’, {‘form’: form})
自定义校验规则
我们希望“ 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_ 开头, 并以字段名称结束。 如果有这样的方法, 它将在校验时被调用。
指定标签
像在模块中做过的那样, 我们同样 可以自定义字段的标签。 仅需使用label, 像 这样:
class ContactForm(forms.Form):
subject = forms.CharField(max_length=100)
email = forms.EmailField(required=False, **label=’Your e-mail address’** )
message = forms.CharField(widget=forms.Textarea)
定制Form 设计
修改form 的显示的最快捷的方 式是使用CSS 。 尤其是错误列表, 可以增强视觉效果。自动生成的错误列表精
确的使用“ <ul class=”errorlist”>“, 这样, 我们就可以针对它们使用CSS 。 下面的CSS 让错误更加醒目
了:
<style type=”text/css”>
ul.errorlist {
margin: 0;
padding: 0;
}
.errorlist li {
background-color: red;
color: white;
display: block;
font-size: 10px;
margin: 0 0 3px;
padding: 4px 5px;
}
</style>
每一个字段部件(<input type=”text”>, <select>, <textarea>, 或者类似) 都可以通过访问{{form. 字段名}} 进行单独的渲染。
<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”>
<div class=”field”>
{{ form.subject.errors }}
<label for=”id_subject”>Subject:</label>
{{ form.subject }}
</div>
<div class=”field”>
{{ form.email.errors }}
<label for=”id_email”>Your e-mail address:</label>
{{ form.email }}
</div>
<div class=”field”>
{{ form.message.errors }}
<label for=”id_message”>Message:</label>
{{ form.message }}
</div>
<input type=”submit” value=”Submit”>
</form>
</body>
</html>
{{ form.message.errors }} 会在 <ul class=”errorlist”> 里面显示, 如果字段是合法的, 或者form 没 有被绑定, 就显示一个空字符串。 我们还可以把 form.message.errors 当作一个布尔值或者当它是list 在 上面做迭代, 例如:
<div class=”field{% if form.message.errors %} errors{% endif %}”>
{% if form.message.errors %}
<ul>
{% for error in form.message.errors %}
<li><strong>{{ error }}</strong></li>
{% endfor %}
</ul>
{% endif %}
<label for=”id_message”>Message:</label>
{{ form.message }}
</div>
在校验失败的情况下, 这段代码 会在包含错误字段的div 的class 属性中增加一个”errors”, 在一个有序列表中显示错误信息。