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 面向对象 成员的访问约束
Dec 23 Python
python实现用于测试网站访问速率的方法
May 26 Python
详解Python编程中基本的数学计算使用
Feb 04 Python
python学习必备知识汇总
Sep 08 Python
Python爬虫实例_利用百度地图API批量获取城市所有的POI点
Jan 10 Python
详解Python3中ceil()函数用法
Feb 19 Python
Django框架中间件(Middleware)用法实例分析
May 24 Python
简单了解Pandas缺失值处理方法
Nov 16 Python
Python 面向对象静态方法、类方法、属性方法知识点小结
Mar 09 Python
Python实现读取并写入Excel文件过程解析
May 27 Python
python re模块常见用法例举
Mar 01 Python
python保存图片的四个常用方法
Feb 28 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 Global定义全局变量使用说明
2013/08/15 PHP
phpQuery采集网页实现代码实例
2020/04/02 PHP
基于ThinkPHP删除目录及目录文件函数
2020/10/28 PHP
jQuery渐变发光导航菜单的实例代码
2013/03/27 Javascript
JS获取屏幕,浏览器窗口大小,网页高度宽度(实现代码)
2013/12/17 Javascript
js获得网页背景色和字体色的方法
2014/03/21 Javascript
node.js中的fs.fchownSync方法使用说明
2014/12/16 Javascript
深入浅析NodeJs并发异步的回调处理
2015/12/21 NodeJs
js面向对象的写法
2016/02/19 Javascript
设置点击文本框或图片弹出日历控件的实现代码
2016/05/12 Javascript
Google 地图API Map()构造器详解
2016/08/06 Javascript
jquery 校验中国身份证号码实例详解
2017/04/11 jQuery
微信小程序教程系列之新建页面(4)
2017/04/17 Javascript
Vuex之理解Mutations的用法实例
2017/04/19 Javascript
Bootstrap 模态框多次显示后台提交多次BUG的解决方法
2017/12/26 Javascript
Vue中父子组件通讯之todolist组件功能开发
2018/05/21 Javascript
JS实现图片转换成base64的各种应用场景实例分析
2018/06/22 Javascript
node.js基于socket.io快速实现一个实时通讯应用
2019/04/23 Javascript
vue改变对象或数组时的刷新机制的方法总结
2019/04/24 Javascript
在Vue mounted方法中使用data变量详解
2019/11/05 Javascript
javascript设计模式 ? 访问者模式原理与用法实例分析
2020/04/26 Javascript
jQuery实现动态加载瀑布流
2020/09/01 jQuery
详解Django通用视图中的函数包装
2015/07/21 Python
Python随机函数库random的使用方法详解
2019/08/21 Python
将tensorflow模型打包成PB文件及PB文件读取方式
2020/01/23 Python
AmazeUI中各种的导航式菜单与解决方法
2020/08/19 HTML / CSS
Expedia印度:您的一站式在线旅游网站
2017/08/24 全球购物
意大利男装网店:Vrients
2019/05/02 全球购物
室内设计自我鉴定
2013/10/15 职场文书
传媒专业推荐信范文
2013/11/23 职场文书
高三毕业生自我鉴定
2013/12/20 职场文书
官僚主义现象查摆问题整改措施
2014/10/04 职场文书
募捐感谢信
2015/01/22 职场文书
小学国庆节活动总结
2015/03/23 职场文书
2015年教师节慰问信
2015/03/23 职场文书
七年级话题作文之执着
2019/11/19 职场文书