Django的HttpRequest和HttpResponse对象详解


Posted in Python onJanuary 26, 2018

本文研究的主要是Django的HttpRequest和HttpResponse对象的相关内容,具体如下。

请求一张页面时,Django把请求的metadata数据包装成一个HttpRequest对象,然后Django加载合适的view方法,把这个HttpRequest 对象作为第一个参数传给view方法。任何view方法都应该返回一个HttpResponse对象。
我们在本书中大量使用这两个对象;本附录详细解释HttpRequest和HttpResponse对象。

HttpRequest

HttpRequest代表一个来自uesr-agent的HTTP请求。

大多重要的请求信息都是作为HttpRequest 对象的属性出现(see Table H-1). 除了session外,其他所有属性都是只读的。

Table H-1. HttpRequest对象的属性

Attribute Description
path 请求页面的全路径,不包括域名—例如, "/music/bands/the_beatles/"。
method 请求中使用的HTTP方法的字符串表示。全大写表示。例如: if request.method == 'GET':     do_something() elif request.method == 'POST':     do_something_else()
GET 包含所有HTTP GET参数的类字典对象。参见QueryDict 文档。
POST 包含所有HTTP POST参数的类字典对象。参见QueryDict 文档。 服务器收到空的POST请求的情况也是有可能发生的。也就是说,表单form通过HTTP POST方法提交请求,但是表单中可以没有数据。因此,不能使用语句if request.POST来判断是否使用HTTP POST方法;应该使用if request.method == "POST" (参见本表的method属性)。 注意: POST不包括file-upload信息。参见FILES属性。
REQUEST 为了方便,该属性是POST和GET属性的集合体,但是有特殊性,先查找POST属性,然后再查找GET属性。借鉴PHP's $_REQUEST。 例如,如果GET = {"name": "john"} 和POST = {"age": '34'},则 REQUEST["name"] 的值是"john", REQUEST["age"]的值是"34". 强烈建议使用GET and POST,因为这两个属性更加显式化,写出的代码也更易理解。
COOKIES 包含所有cookies的标准Python字典对象。Keys和values都是字符串。参见第12章,有关于cookies更详细的讲解。
FILES 包含所有上传文件的类字典对象。FILES中的每个Key都是标签中name属性的值. FILES中的每个value 同时也是一个标准Python字典对象,包含下面三个Keys: filename: 上传文件名,用Python字符串表示 content-type: 上传文件的Content type content: 上传文件的原始内容 注意:只有在请求方法是POST,并且请求页面中
有enctype="multipart/form-data"属性时FILES才拥有数据。否则,FILES 是一个空字典。
META 包含所有可用HTTP头部信息的字典。 例如: CONTENT_LENGTH CONTENT_TYPE QUERY_STRING: 未解析的原始查询字符串 REMOTE_ADDR: 客户端IP地址 REMOTE_HOST: 客户端主机名 SERVER_NAME: 服务器主机名 SERVER_PORT: 服务器端口 META 中这些头加上前缀HTTP_最为Key, 例如: HTTP_ACCEPT_ENCODING HTTP_ACCEPT_LANGUAGE HTTP_HOST: 客户发送的HTTP主机头信息 HTTP_REFERER: referring页 HTTP_USER_AGENT: 客户端的user-agent字符串 HTTP_X_BENDER: X-Bender头信息
user 是一个django.contrib.auth.models.User 对象,代表当前登录的用户。如果访问用户当前没有登录,user将被初始化为django.contrib.auth.models.AnonymousUser的实例。你可以通过user的is_authenticated()方法来辨别用户是否登录: if request.user.is_authenticated():     # Do something for logged-in users. else:     # Do something for anonymous users. 只有激活Django中的AuthenticationMiddleware时该属性才可用 关于认证和用户的更详细讲解,参见第12章。
session 唯一可读写的属性,代表当前会话的字典对象。只有激活Django中的session支持时该属性才可用。 参见第12章。
raw_post_data 原始HTTP POST数据,未解析过。 高级处理时会有用处。

Request对象也有一些有用的方法,见Table H-2:

Table H-2. HttpRequest Methods
Method Description
__getitem__(key) 返回GET/POST的键值,先取POST,后取GET。如果键不存在抛出 KeyError。 这是我们可以使用字典语法访问HttpRequest对象。 例如,request["foo"]等同于先request.POST["foo"] 然后 request.GET["foo"]的操作。
has_key() 检查request.GET or request.POST中是否包含参数指定的Key。
get_full_path() 返回包含查询字符串的请求路径。例如, "/music/bands/the_beatles/?print=true"
is_secure() 如果请求是安全的,返回True,就是说,发出的是HTTPS请求。

QueryDict对象

在HttpRequest对象中, GET和POST属性是django.http.QueryDict类的实例。 QueryDict类似字典的自定义类,用来处理单键对应多值的情况。因为一些HTML form元素,例如,<selectmultiple="multiple">, 就会传多个值给单个键。

QueryDict对象是immutable(不可更改的),除非创建它们的copy()。这意味着我们不能直接改变request.POST and request.GET的属性。

QueryDict实现所有标准的字典方法。还包括一些特有的方法,见Table H-3.

Table H-3. How QueryDicts Differ from Standard Dictionaries.
Method Differences from Standard dict Implementation
__getitem__ 和标准字典的处理有一点不同,就是,如果Key对应多个Value,__getitem__()返回最后一个value。
__setitem__ 设置参数指定key的value列表(一个Python list)。注意:它只能在一个mutable QueryDict 对象上被调用(就是通过copy()产生的一个QueryDict对象的拷贝).
get() 如果key对应多个value,get()返回最后一个value。
update() 参数可以是QueryDict,也可以是标准字典。和标准字典的update方法不同,该方法添加字典 items,而不是替换它们: >>> q = QueryDict('a=1') >>> q = q.copy() # to make it mutable >>> q.update({'a': '2'}) >>> q.getlist('a')  ['1', '2'] >>> q['a'] # returns the last ['2']
items() 和标准字典的items()方法有一点不同,该方法使用单值逻辑的__getitem__(): >>> q = QueryDict('a=1&a=2&a=3') >>> q.items() [('a', '3')]
values() 和标准字典的values()方法有一点不同,该方法使用单值逻辑的__getitem__():

此外, QueryDict也有一些方法,见Table H-4.

H-4. 额外的 (非字典的) QueryDict 方法
Method Description
copy() 返回对象的拷贝,内部实现是用Python标准库的copy.deepcopy()。该拷贝是mutable(可更改的) — 就是说,可以更改该拷贝的值。
getlist(key) 返回和参数key对应的所有值,作为一个Python list返回。如果key不存在,则返回空list。 It's guaranteed to return a list of some sort..
setlist(key,list_) 设置key的值为list_ (unlike __setitem__()).
appendlist(key,item) 添加item到和key关联的内部list.
setlistdefault(key,list) 和setdefault有一点不同,它接受list而不是单个value作为参数。
lists() 和items()有一点不同, 它会返回key的所有值,作为一个list, 例如: >>> q = QueryDict('a=1&a=2&a=3') >>> q.lists() [('a', ['1', '2', '3'])]
urlencode() 返回一个以查询字符串格式进行格式化后的字符串(e.g., "a=2&b=3&b=5").

A Complete Example

例如, 下面是一个HTML form:

<span style="font-size:12px;"><form action="/foo/bar/" method="post"> 
<input type="text" name="your_name" /> 
<select multiple="multiple" name="bands">  
  <option value="beatles">The Beatles</option> 
  <option value="who">The Who</option> 
  <option value="zombies">The Zombies</option> 
</select> 
<input type="submit" /> 
</form></span>

如果用户在your_name域中输入"JohnSmith",同时在多选框中选择了“The Beatles”和“The Zombies”,下面是Django请求对象的内容:

>>> request.GET{} 
>>> request.POST 
{'your_name': ['John Smith'], 'bands': ['beatles', 'zombies']} 
>>> request.POST['your_name'] 
'John Smith'  
>>> request.POST['bands'] 
'zombies' 
>>> request.POST.getlist('bands') 
['beatles', 'zombies'] 
>>> request.POST.get('your_name', 'Adrian') 
'John Smith' 
>>> request.POST.get('nonexistent_field', 'Nowhere Man') 
'Nowhere Man'

HttpResponse

对于HttpRequest 对象来说,是由Django自动创建, 但是,HttpResponse对象就必须我们自己创建。每个View方法必须返回一个HttpResponse对象。

HttpResponse类在django.http.HttpResponse。

构造HttpResponses

一般地, 你可以通过给HttpResponse的构造函数传递字符串表示的页面内容来构造HttpResponse对象:

>>> response = HttpResponse("Here's the text of the Web page.") 
>>> response = HttpResponse("Text only, please.", mimetype="text/plain")

但是如果想要增量添加内容, 你可以把response当作filelike对象使用:

>>> response = HttpResponse() 
>>> response.write("<p>Here's the text of the Web page.</p>") 
>>> response.write("<p>Here's another paragraph.</p>")

也可以给HttpResponse传递一个iterator作为参数,而不用传递硬编码字符串。 如果你使用这种技术, 下面是需要注意的一些事项:

· iterator应该返回字符串.

· 如果HttpResponse使用iterator进行初始化,就不能把HttpResponse实例作为filelike 对象使用。这样做将会抛出异常。

最后,再说明一下,HttpResponse实现了write()方法, 可以在任何需要filelike对象的地方使用HttpResponse对象。参见第11章,有一些例子。

设置Headers

你可以使用字典语法添加,删除headers:

>>> response = HttpResponse()  
>>> response['X-DJANGO'] = "It's the best." 
>>> del response['X-PHP'] 
>>> response['X-DJANGO'] 
"It's the best."

你也可以使用has_header(header)方法检测某个header是否存在。

不要手动设置Cookie headers;具体的做法,参见第12章,有关于怎样在Django中处理cookies的详细讲解。

HttpResponse子类

Django包含很多HttpResponse子类,用来处理不同的HTTP响应类型(见Table H-5). 和HttpResponse一样, 这些子类在django.http中.

Table H-5. HttpResponse Subclasses
Class Description
HttpResponseRedirect 构造函数接受单个参数:重定向到的URL。可以是全URL (e.g., 'http://search.yahoo.com/')或者相对URL(e.g., '/search/'). 注意:这将返回HTTP状态码302。
HttpResponsePermanentRedirect 同HttpResponseRedirect一样,但是返回永久重定向(HTTP 状态码 301)。
HttpResponseNotModified 构造函数不需要参数。Use this to designate that a page hasn't been modified since the user's last request.
HttpResponseBadRequest 返回400 status code。
HttpResponseNotFound 返回404 status code.
HttpResponseForbidden 返回403 status code.
HttpResponseNotAllowed 返回405 status code. 它需要一个必须的参数:一个允许的方法的list (e.g., ['GET','POST']).
HttpResponseGone 返回410 status code.
HttpResponseServerError 返回500 status code.

当然,你也可以自己定义不包含在上表中的HttpResponse子类。

返回Errors

在Django中返回HTTP错误码是很容易的。上面介绍了HttpResponseNotFound, HttpResponseForbidden, HttpResponseServerError等一些子类。View方法中返回这些子类的实例就OK了,例如:

def my_view(request):   
  # ...   
  if foo:     
     return HttpResponseNotFound('<h1>Page not found</h1>')   
  else:     
     return HttpResponse('<h1>Page was found</h1>')

当返回HttpResponseNotFound时,你需要定义错误页面的HTML:

return HttpResponseNotFound('<h1>Page not found</h1>')

因为404错误是最常使用的HTTP错误, 有一个更方便的方法处理它。

为了方便,而且整个站点有一致的404错误页面也是友好的,Django提供一个Http404异常类。如果在一个View方法中抛出Http404,Django将会捕获它并且返回标准错误页面,同时返回错误码404。

from django.http import Http404 
 
def detail(request, poll_id):   
  try:     
    p = Poll.objects.get(pk=poll_id)   
  except Poll.DoesNotExist:     
     raise Http404   
  return render_to_response('polls/detail.html', {'poll': p})

为了使用Http404异常, 你需要创建一个模板文件。当异常抛出时,就会显示该模板文件。该模板文件的文件名是404.html,在模板根目录下创建。

自定义404 (Not Found) View方法

当抛出Http404异常时, Django会加载一个特殊的view方法处理404错误。默认地, 它是django.views.defaults.page_not_found,负责加载和渲染404.html模板文件。

这意味着我们必须在模板根目录定义404.html模板文件,该模板文件应用于所有的404异常。

该page_not_found view方法应该可以应对几乎99%的Web App,但是如果想要重载该view方法时, 你可以在URLConf文件中指定handler404为自定义的404 errpr view方法, 像这样:

from django.conf.urls.defaults import * 
 
urlpatterns = patterns('',   
  ... 
) 
 
handler404 = 'mysite.views.my_custom_404_view'

Django就是通过在URLConf文件中查找handler404来决定404 view方法的。默认地, URLconfs包含下面一行代码:

from django.conf.urls.defaults import *

在 django/conf/urls/defaults.py模块中, handler404赋值为 'django.views.defaults.page_not_found'。

注意:

· 如果请求URL没有和Django的URLConf文件中的任何一个正则表示式匹配,404 view方法就会被调用。

· 如果没有定义自己的404 view — 使用默认地404 view,你仍然有一个工作要做:在模板根目录创建404.html模板文件。默认地404 view将使用该模板处理所有404错误。

· 如果 DEBUG设置为True (在setting模块中),404 view方法不会被使用,取而代之的是,traceback信息。

自定义500 (Server Error) View方法

同样地,当view代码发生运行时错误时,Django也会产生特殊行为。如果view方法产生异常,Django将会调用默认地view方法django.views.defaults.server_error, 该方法加载渲染500.html模板文件。

这意味着我们必须在模板根目录定义500.html模板文件,该模板文件应用于所有的服务器错误。

该server_error view方法应该可以应对几乎99%的Web App,但是如果想要重载该view方法时, 你可以在URLConf文件中指定handler500为自定义的server error view方法, 像这样:

from django.conf.urls.defaults import * 
 
  urlpatterns = patterns('',   
 
    ... 
 
  )  
 
  handler500 = 'mysite.views.my_custom_error_view'

翻译文章来源 (Django官网文档):https://docs.djangoproject.com/en/1.9/ref/request-response/#django.http.HttpRequest
其中进行了一些整理。

总结

以上就是本文关于Django的HttpRequest和HttpResponse对象详解的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

Python 相关文章推荐
Python的Django框架中模板碎片缓存简介
Jul 24 Python
python中执行shell的两种方法总结
Jan 10 Python
Python正则抓取新闻标题和链接的方法示例
Apr 24 Python
python逐行读写txt文件的实例讲解
Apr 03 Python
selenium+python自动化测试之环境搭建
Jan 23 Python
Django Rest framework权限的详细用法
Jul 25 Python
Python Opencv提取图片中某种颜色组成的图形的方法
Sep 19 Python
基于python中__add__函数的用法
Nov 25 Python
python支持多线程的爬虫实例
Dec 21 Python
Python实现自动访问网页的例子
Feb 21 Python
Django Path转换器自定义及正则代码实例
May 29 Python
Python将CSV文件转化为HTML文件的操作方法
Jun 30 Python
Python编程实现的简单神经网络算法示例
Jan 26 #Python
Django使用httpresponse返回用户头像实例代码
Jan 26 #Python
Django rest framework基本介绍与代码示例
Jan 26 #Python
Python实现PS图像调整之对比度调整功能示例
Jan 26 #Python
Python实现PS滤镜特效之扇形变换效果示例
Jan 26 #Python
修复CentOS7升级Python到3.6版本后yum不能正确使用的解决方法
Jan 26 #Python
Python实现PS滤镜功能之波浪特效示例
Jan 26 #Python
You might like
PHP读取ACCESS数据到MYSQL的代码
2011/05/11 PHP
PHP5中Cookie与 Session使用详解
2013/04/30 PHP
php实现可以设置中奖概率的抽奖程序代码分享
2014/01/19 PHP
测试php连接mysql是否成功的代码分享
2014/01/24 PHP
PHP实现的限制IP投票程序IP来源分析
2016/05/04 PHP
laravel学习教程之关联模型
2016/07/30 PHP
PHP小偷程序的设计与实现方法详解
2016/10/15 PHP
PHP程序员学习使用Swoole的理由
2018/06/24 PHP
用jquery实现的模拟QQ邮箱里的收件人选取及其他效果(一)
2011/01/06 Javascript
jquery实现滑动图片自己测试的例子
2013/11/05 Javascript
使用jquery操作session方法分享
2015/01/22 Javascript
JavaScript制作windows经典扫雷小游戏
2015/03/31 Javascript
jQuery实现给页面换肤的方法
2015/05/30 Javascript
JavaScript学习小结(一)——JavaScript入门基础
2015/09/02 Javascript
jQuery插件Validate实现自定义校验结果样式
2016/01/18 Javascript
JS动态插入并立即执行回调函数的方法
2016/04/21 Javascript
AngularJS基础 ng-switch 指令简单示例
2016/08/03 Javascript
js中常用的Tab切换效果(推荐)
2016/08/30 Javascript
jQuery实现的仿百度,仿谷歌搜索下拉框效果示例
2016/12/30 Javascript
react-native中ListView组件点击跳转的方法示例
2017/09/30 Javascript
JavaScript重复元素处理方法分析【统计个数、计算、去重复等】
2017/12/14 Javascript
vue-music 使用better-scroll遇到轮播图不能自动轮播问题
2018/12/03 Javascript
axios如何利用promise无痛刷新token的实现方法
2019/08/27 Javascript
JS数组方法shift()、unshift()用法实例分析
2020/01/18 Javascript
python利用hook技术破解https的实例代码
2013/03/25 Python
python的类方法和静态方法
2014/12/13 Python
Python 性能优化技巧总结
2016/11/01 Python
Python使用Dijkstra算法实现求解图中最短路径距离问题详解
2018/05/16 Python
Numpy 将二维图像矩阵转换为一维向量的方法
2018/06/05 Python
python进阶之自定义可迭代的类
2019/08/20 Python
Smallable英国家庭概念店:设计师童装及家居装饰
2017/07/05 全球购物
英国团购网站:Groupon英国
2017/11/28 全球购物
缓刑人员思想汇报500字
2014/09/12 职场文书
指导教师推荐意见
2015/06/05 职场文书
安全教育的主题班会
2015/08/13 职场文书
通过T-SQL语句创建游标与实现数据库加解密功能
2022/03/16 SQL Server