从request对象中获取数据
我们在第三章讲述view的函数时已经介绍过httprequest对象了,但当时并没有讲太多。 让我们回忆下:每个view函数的第一个参数是一个httprequest对象,就像下面这个hello()函数:
from django.http import httpresponse
def hello(request):
return httpresponse(“hello world”)
httprequest对象,比如上面代码里的request变量,会有一些有趣的、你必须让自己熟悉的属性和方法,以便知道能拿它们来做些什么。 在view函数的执行过程中,你可以用这些属性来获取当前request的一些信息(比如,你正在加载这个页面的用户是谁,或者用的是什么浏览器)。
url相关信息
httprequest对象包含当前请求url的一些信息:
在view函数里,要始终用这个属性或方法来得到url,而不要手动输入。 这会使得代码更加灵活,以便在其它地方重用。 下面是一个简单的例子:
# bad!
def current_url_view_bad(request):
return httpresponse(“welcome to the page at /current/”)
# good
def current_url_view_good(request):
return httpresponse(“welcome to the page at %s” % request.path)
有关request的其它信息
request.meta 是一个python字典,包含了所有本次http请求的header信息,比如用户ip地址和用户agent(通常是浏览器的名称和版本号)。 注意,header信息的完整列表取决于用户所发送的header信息和服务器端设置的header信息。 这个字典中几个常见的键值有:
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” 。)
注意,因为 request.meta 是一个普通的python字典,因此当你试图访问一个不存在的键时,会触发一个keyerror异常。 (http header信息是由用户的浏览器所提交的、不应该给予信任的“额外”数据,因此你总是应该好好设计你的应用以便当一个特定的header数据不存在时,给出一个优雅的回应。)你应该用 try/except 语句,或者用python字典的 get() 方法来处理这些“可能不存在的键”:
# bad!
def ua_display_bad(request):
ua = request.meta[‘http_user_agent’] # might raise keyerror!
return httpresponse(“your browser is %s” % ua)
# 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)
我们鼓励你动手写一个简单的view函数来显示 request.meta 的所有数据,这样你就知道里面有什么了。 这个view函数可能是这样的:
def display_meta(request):
values = request.meta.items()
values.sort()
html = []
for k, v in values:
html.append(‘%s%s’ % (k, v))
return httpresponse(‘%s’ % ‘\n’.join(html))
做为一个练习,看你自己能不能把上面这个view函数改用django模板系统来实现,而不是上面这样来手动输入html代码。 也可以试着把前面提到的 request.path 方法或 httprequest 对象的其它方法加进去。