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 相关文章推荐
简介Django框架中可使用的各类缓存
Jul 23 Python
python 网络编程常用代码段
Aug 28 Python
python实现word 2007文档转换为pdf文件
Mar 15 Python
Python Grid使用和布局详解
Jun 30 Python
Python创建字典的八种方式
Feb 27 Python
Python 使用matplotlib模块模拟掷骰子
Aug 08 Python
python命名空间(namespace)简单介绍
Aug 10 Python
K近邻法(KNN)相关知识总结以及如何用python实现
Jan 28 Python
matplotlib部件之套索Lasso的使用
Feb 24 Python
Python代码风格与编程习惯重要吗?
Jun 03 Python
Python干货实战之八音符酱小游戏全过程详解
Oct 24 Python
讲解Python实例练习逆序输出字符串
May 06 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中设置多级目录session的问题
2011/08/08 PHP
PHP图片处理之使用imagecopyresampled函数裁剪图片例子
2014/11/19 PHP
php实现过滤字符串中的中文和数字实例
2015/07/29 PHP
十个PHP高级应用技巧果断收藏
2015/09/25 PHP
iis6+javascript Add an Extension File
2007/06/13 Javascript
解决jquery .ajax 在IE下卡死问题的解决方法
2009/10/26 Javascript
jquery.boxy插件的iframe扩展代码
2010/07/02 Javascript
JQUBar 基于JQUERY的柱状图插件
2010/11/23 Javascript
JQuery制作的放大效果的popup对话框(未添加任何jquery plugin)分享
2013/04/28 Javascript
JQuery中关于jquery.js与jquery.min.js的比较探讨
2013/05/15 Javascript
jqgrid 编辑添加功能详细解析
2013/11/08 Javascript
jquery ajax修改全局变量示例代码
2013/11/08 Javascript
三种动态加载js的jquery实例代码另附去除js方法
2014/04/30 Javascript
JsRender实用入门教程
2014/10/31 Javascript
Node.JS中事件轮询(Event Loop)的解析
2017/02/25 Javascript
JavaScript 判断对象中是否有某属性的常用方法
2018/06/14 Javascript
解决echarts图表使用v-show控制图表显示不全的问题
2020/07/19 Javascript
理解JavaScript中的Proxy 与 Reflection API
2020/09/21 Javascript
修改NPM全局模式的默认安装路径的方法
2020/12/15 Javascript
[01:03:47]VP vs NewBee Supermajor 胜者组 BO3 第一场 6.5
2018/06/06 DOTA
python通过ffmgep从视频中抽帧的方法
2018/12/05 Python
如何给Python代码进行加密
2020/01/10 Python
关于canvas.toDataURL 在iOS运行失败的问题解决
2020/09/16 HTML / CSS
加拿大领先的优质厨具产品在线购物网站:Golda’s Kitchen
2017/11/17 全球购物
一套VC试题
2015/01/23 面试题
个人找工作求职简历的自我评价
2013/10/20 职场文书
小学家长通知书评语
2014/12/31 职场文书
公司催款律师函
2015/05/27 职场文书
交通事故协议书范本
2016/03/19 职场文书
2019年度开业庆典祝福语大全!
2019/07/05 职场文书
Oracle笔记
2021/04/05 Oracle
python - asyncio异步编程
2021/04/06 Python
解析CSS 提取图片主题色功能(小技巧)
2021/05/12 HTML / CSS
django学习之ajax post传参的2种格式实例
2021/05/14 Python
Python 图片添加美颜效果
2022/04/28 Python
数据设计之权限的实现
2022/08/05 MySQL