附录H HTTP请求(Request)和回应(Response)对象

57
http://djangobook.py3k.cn/

Django使用request和response对象在系统间传递状态。

 

当一个页面被请示时,Django创建一个包含请求元数据的 HttpRequest 对象。 然后Django调入合适的视图,把 HttpRequest 作为视图函数的第一个参数 传入。每个视图要负责返回一个 HttpResponse 对象。

 

我们在书中已经使用过这些对象了;这篇附录说明了 HttpRequestHttpResponse 的全部API。

 

HttpRequest对象

 

HttpRequest 表示来自某客户端的一个单独的HTTP请求。

1

HttpRequest实例的属性包含了关于此次请求的大多数重要信息(详见表H-1)。 除了session外的所有属性都应该认为是只读的.

 
表 H-1. HttpRequest对象的属性
属性 描述
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提交的请求有可能包含一个空的 POST 字典, 也就是说, 一个通过POST方法提交的表单可能不包含数据。 因此,不应该使用 if request.POST 来判断POST方法的使用, 而是使用 if request.method == "POST" (见表中的 method 条目)。

注意: POST 包含文件上传信息。 见 FILES

REQUEST

为了方便而创建,这是一个类字典对象,先搜索 POST , 再搜索 GET 。 灵感来自于PHP的 $_REQEUST

例如, 若 GET = {"name": "john"}POST = {"age": '34'}REQUEST["name"] 会是 "john"REQUEST["age"] 会是 "34"

强烈建议使用 GETPOST ,而不是 REQUEST 。 这是为了向前兼容和更清楚的表示。

COOKIES 一个标准的Python字典,包含所有cookie。 键和值都是字符串。cookie使用的更多信息见第12章。
FILES

一个类字典对象,包含所有上传的文件。 FILES 的键来自 <input type="file" name="" /> 中的 nameFILES 的值是一个标准的Python字典, 包含以下三个键:

  • filename :字符串,表示上传文件的文件名。
  • content-type :上传文件的内容类型。
  • content :上传文件的原始内容。

注意 FILES 只在请求的方法是 POST ,并且提交的 <form> 包含 enctype="multipart/form-data" 时 才包含数据。否则, FILES 只是一个空的类字典对象。

META

一个标准的Python字典,包含所有有效的HTTP头信息。 有效的头信息与客户端和服务器有关。 这里有几个例子:

  • CONTENT_LENGTH
  • CONTENT_TYPE
  • QUERY_STRING :未解析的原始请求字符串。
  • REMOTE_ADDR :客户端IP地址。
  • REMOTE_HOST :客户端主机名。
  • SERVER_NAME :服务器主机名。
  • SERVER_PORT :服务器端口号。

META 中有效的任一HTTP头信息都是带有 HTTP_ 前缀的 键,例如:

  • HTTP_ACCEPT_ENCODING
  • HTTP_ACCEPT_LANGUAGE
  • HTTP_HOST :客户端发送的 Host 头信息。
  • HTTP_REFERER :被指向的页面,如果存在的。
  • HTTP_USER_AGENT :客户端的user-agent字符串。
  • HTTP_X_BENDERX-Bender 头信息的值, 如果已设的话。
user

一个 django.contrib.auth.models.User 对象表示 当前登录用户。 若当前用户尚未登录, user 会设为 django.contrib.auth.models.AnonymousUser 的一个实例。 可以将它们与 is_authenticated() 区别开:

if request.user.is_authenticated():
# Do something for logged-in users.
else:
# Do something for anonymous users.

user 仅当Django激活 AuthenticationMiddleware 时有效。

关于认证和用户的完整细节,见第12章。

session 一个可读写的类字典对象,表示当前session。 仅当Django已激活session支持时有效。 见第12章。
raw_post_data POST的原始数据。 用于对数据的复杂处理。

Request对象同样包含了一些有用的方法,见表H-2。

 
表 H-2. HttpRequest 的方法
方法 描述
__getitem__(key)

请求所给键的GET/POST值,先查找POST,然后是GET。 若键不存在,则引发异常 KeyError

该方法使用户可以以访问字典的方式来访问一个 HttpRequest 实例。

例如, request["foo"] 和先检查 request.POST["foo"] 再检查 request.GET["foo"] 一 样。

has_key() 返回 TrueFalse , 标识 request.GETrequest.POST 是否包含所给的 键。
get_full_path() 返回 path ,若请求字符串有效,则附加于其后。 例如, "/music/bands/the_beatles/?print=true"
is_secure() 如果请求是安全的,则返回 True 。 也就是说,请求是以HTTPS的形式提交的。

QueryDict 对象

 

在一个 HttpRequest 对象中, GETPOST 属性都是 django.http.QueryDict 的实例。 QueryDict 是一个类似于字典的类,专门用来处理用一个键的多值。当处理一些HTML表单中的元素,特别是 <select multiple="multiple"> 之类传递同一key的多值的元素时,就需要这个类了。

 

QueryDict 实例是不可变的,除非创建了一个 copy() 副本。也就是说不能直接更改 request.POSTrequest.GET 的属性。

 

QueryDict 实现了所有标准的字典的方法,因为它正是字典的一个子类。与其不同的东西都已在表H-3中列出。

 
表 H-3. QueryDicts 与标准字典的区别
方法 与标准字典实现的不同
__getitem__ 与一个字典一样。但是,当一个键有多个值时, __getitem__() 返回最后一个值。
__setitem__ 将所给键的值设为 [value] (一个只有一个 value 元素的 Python列表)。 注意,因对其它的字典函数有副作用,故它只能被称 为一个可变的 QueryDict (通过 copy() 创建)。
get() 如果一个键多个值,和 __getitem__ 一样, get() 返回 最后一个值。
update()
参数是一个 QueryDict 或标准字典。 和标准字典的
update 不同,这个方法*增加*而不是替换一项内容:
>>> q = QueryDict('a=1')
>>> q = q.copy() # 使其可变
>>> q.update({'a': '2'})
>>> q.getlist('a')
['1', '2']
>>> q['a'] # 返回最后一个值
['2']
items()

和标准字典的 items() 方法一样, 不同的是它和 __getitem()__ 一样,返回最后一个值:

>>> q = QueryDict('a=1&a=2&a=3')
>>> q.items()
[('a', '3')]
values() 和标准字典的 values() 方法一样, 不同的是它和 __getitem()__ 一样,返回最后一个值。

另外, QueryDict 还有在表H-4中列出的方法。

 
表 H-4. 附加的 (非字典的) QueryDict 方法
方法 描述
copy() 返回一个对象的副本,使用的是Python标准库中的 copy.deepcopy() 。 该副本是可变的, 也就是说,你能改变它的值。
getlist(key) 以Python列表的形式返回所请求键的数据。 若键不存在则返回空列表。 它保证了一定会返回某种形式的list。
setlist(key, list_) 将所给键的键值设为 list_ (与 __setitem__() 不同)。
appendlist(key, item) key 相关的list上增加 item
setlistdefault(key, l) setdefault 一样, 不同的是它的第二个参数是 一个列表,而不是一个值。
lists()

items() 一样, 不同的是它以一个列表的形式 返回字典每一个成员的所有值。 例如:

>>> q = QueryDict('a=1&a=2&a=3')
>>> q.lists()
[('a', ['1', '2', '3'])]
urlencode() 返回一个请求字符串格式的数据字符串 (如, "a=2&b=3&b=5" )。

一个完整的例子

 

例如, 给定这个HTML表单:

 
<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>
1

如果用户在 your_name 中输入 "John Smith" ,并且在多选框中同时选择了The Beatles和The Zombies,那么以下就是Django的request对象所拥有的:

 
>>> 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'
 

使用时请注意:

 

GET , POST , COOKIES , FILES , META , REQUEST , raw_post_datauser 这些属性都是延迟加载的。 也就是说除非代码中访问它们,否则Django并不会花费资源来计算这些属性值。

 

HttpResponse

 

与Django自动创建的 HttpRequest 对象相比, HttpResponse 对象则是由你创建的。 你创建的每个视图都需要实例化,处理和返回一个 HttpResponse 对象。

1

HttpResponse 类存在于 django.http.HttpResponse

 

构造HttpResponse

 

一般情况下,你创建一个 HttpResponse 时,以字符串的形式来传递页面的内容给 HttpResponse 的构造函数:

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

但是如果希望逐渐增加内容,则可以把 response 当作一个类文件对象使用:

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

你可以将一个迭代器传递给 HttpResponse ,而不是固定的字符串。如果你要这样做的话,请遵循以下规则:

 
  • 迭代器应返回字符串。

     
     
     
  • 若一个 HttpResponse 已经通过实例化,并以一个迭代器作为其内容,就不能以一个类文件对象使用 HttpResponse 实例。这样做的话,会导致一个 Exception

     
     
     

最后,注意 HttpResponse 实现了一个 write() 方法,使其可以在任何可以使用类文件对象的地方使用。 这方面的例子见第11章。

 

设置 Headers

 

您可以使用字典一样地添加和删除头信息。

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

你也可以使用 has_header(header) 来检查一个头信息项是否存在。

 

请避免手工设置 Cookie 头,参见第12章Django中cookie工作原理的说明。

 

HttpResponse的子类

 

Django包含许多处理不同类型的HTTP请求的 HttpResponse 子类(见表H-5)。像 HttpResponse 一样,这些类在 django.http 中。

 

System Message: ERROR/3 (<string>, line 537)

Error parsing content block for the “table” directive: exactly one table expected.

 
.. table:: 表 H-5. HttpResponse 子类

    +---------------------------------+-------------------------------------------+
|类名 |描述 |
+=================================+===========================================+
|``HttpResponseRedirect`` |构造函数的参数有一个: |
| |重定向的路径。 它可以是一个完整的URL |
| |(例如, ``'http://search.yahoo.com/'`` ) |
| |或者不包括域名的绝对路径(如 |
| |``'/search/'`` )。 注意它返回 |
| |HTTP 状态码 302。 |
+---------------------------------+-------------------------------------------+
|``HttpResponsePermanentRedirect``|类似 ``HttpResponseRedirect`` , 但是它 |
| |返回一个永久重定向 (HTTP 状态码 301), |
| |而不是暂时性重定向(状态码302)。 |
+---------------------------------+-------------------------------------------+
|``HttpResponseNotModified`` |构造函数没有任何参数。 |
| |用它来表示这个页面在上次请求后未改变。 |
+---------------------------------+-------------------------------------------+
|``HttpResponseBadRequest`` |类似 ``HttpResponse`` ,但使用400状态码。 |
+---------------------------------+-------------------------------------------+
|``HttpResponseNotFound`` |类似 ``HttpResponse`` ,但使用404状态码。 |
+---------------------------------+-------------------------------------------+
|``HttpResponseForbidden`` |类似 ``HttpResponse`` ,但使用403状态码。 |
+---------------------------------+-------------------------------------------+
|``HttpResponseNotAllowed`` |类似 ``HttpResponse`` ,但使用405状态码。 |
| |它必须有一个参数: |
| |允许方法的列表。 |
| |(例如, ``['GET', 'POST']`` )。 |
+---------------------------------+-------------------------------------------+
|``HttpResponseGone`` |类似 ``HttpResponse`` ,但使用410状态码。 |
+---------------------------------+-------------------------------------------+
|``HttpResponseServerError`` |类似 ``HttpResponse`` ,但使用500状态码。 |
+---------------------------------+-------------------------------------------+
 

当然,如果框架不支持一些特性,你也可以定义自己的 HttpResponse 子类来处理不同的请求。

 

返回错误

 

在Django中返回HTTP错误代码很容易。我们前面已经提到 HttpResponseNotFoundHttpResponseForbiddenHttpResponseServerError ,和其它子类。为了更好地表示一个错误,只要返回这些子类之一的一个实例,而不是一个通常的 HttpResponse ,例如:

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

至今为止,404错误是最常见的HTTP错误,有一种更容易的方式来处理。

 

当返回一个错误,比如 HttpResponseNotFound 时,需要定义错误页面的HTML:

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

为了方便,而且定义一个通用的应用于网站的404错误页面也是一个很好的选择,Django提供了一个 Http404 异常。如果在视图的任何地方引发 Http404 异常,Django就会捕获错误并返回应用程序的标准错误页面,当然,还有HTTP错误代码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})
1

为了完全发挥出 Http404 的功能,应创建一个模板,在404错误被引发时显示。模板的名字应该是 404.html ,而且应该位于模板树的最高层。

 

自定义 404 (无法找到) 视图

 

当引发 Http404 异常,Django加载一个专门处理404错误的视图。默认情况下,这个视图是 django.views.defaults.page_not_found ,它会加载并显示模板 404.html

 

这意味着需要在根模板目录定义一个 404.html 模板。这个模板会作用于所有404错误。

 

视图 page_not_found 适用于99%的网站应用程序,但若是希望重载该视图,可以在URLconf中指定 handler404 ,就像这样:sfas

 
from django.conf.urls.defaults import *

urlpatterns = patterns('',
...
) handler404 = 'mysite.views.my_custom_404_view'
 

后台执行时,Django以 handler404 来确定404视图。默认情况下,URLconf包含以下内容:

 
from django.conf.urls.defaults import *
1

这句话负责当前模块中的 handler404 设置。正如你所见,在 django/conf/urls/defaults.py 中, handler404 默认被设为 'django.views.defaults.page_not_found'

 

关于404视图,有三点需要注意:

 
  • 当Django在URLconf无法找到匹配的正则表达式时,404视图会显示。

     
     
     
  • 如果没有定义自己的404视图,而只是简单地使用默认的视图,此时就需要在模板目录的根目录创建一个 404.html 模板。默认的404视图会对所有404错误使用改模板。

     
     
     
  • DEBUG 被设为 True (在settings模块内),则404视图不会被使用,此时显示的是跟踪信息。

     
     
     

自定义 500 (服务器错误) 视图

 

同样地,若是在试图代码中出现了运行时错误,Django会进行特殊情况处理。如果视图引发了一个异常,Django会默认访问视图 django.views.defaults.server_error ,加载并显示模板 500.html

 

这意味着需要在根模板目录定义一个 500.html 模板。该模板作用于所有服务器错误。

 

视图 server_error 适用于99%的网站应用程序,但若是希望重载该视图,可以在URLconf中指定 handler500 ,就像这样:

 
from django.conf.urls.defaults import *

urlpatterns = patterns('',
...
) handler500 = 'mysite.views.my_custom_error_view'
 

HTTP请求(Request)和回应(Response)对象的更多相关文章

  1. django HTTP请求(Request)和回应(Response)对象

    Django使用request和response对象在系统间传递状态.—(阿伦)当一个页面被请示时,Django创建一个包含请求元数据的 HttpRequest 对象. 然后Django调入合适的视图 ...

  2. 使用java的自定义过滤器Filter 处理请求request 并响应response

    package com.enation.eop; import java.io.BufferedReader; import java.io.IOException; import java.io.I ...

  3. Javaweb学习笔记——(十)——————response对象,response字符流缓冲器,响应头,状态码,重定向,requset对象,路径和乱码

    请求响应对象: request和response *当服务器接收都请求后,服务器会创建request和response对象,把请求数据封装到request对象中: *然后调用Servlet的sevic ...

  4. node.js入门学习(二)MIME模块,request和response对象,demo之不同url请求不同html页面,页面包含图片、样式css等静态资源

    一.构建http服务程序-根据不同请求做出不同响应 // 加载http模块 var http = require("http"); // 创建一个http服务对象 http.cre ...

  5. request 对象和 response 对象

    Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象.和代表响应的response对象 HttpServletResponse HttpServletR ...

  6. request对象和response对象

    Request 和 Response 对象起到了服务器与客户机之间的信息传递作用.Request 对象用于接收客户端浏览器提交的数据,而 Response 对象的功能则是将服务器端的数据发送到客户端浏 ...

  7. Request和Response对象

    Request 和 Response 对象起到了服务器与客户机之间的信息传递作用.Request 对象用于接收客户端浏览器提交的数据,而 Response 对象的功能则是将服务器端的数据发送到客户端浏 ...

  8. request和response对象的具体介绍

    Request 对象 - request 对象表示 HTTP 请求,包含了请求查询字符串,参数,内容,HTTP 头部等属性.常见属性有:    req.app:当callback为外部文件时,用req ...

  9. 【转】Django中的request与response对象

    关于request与response 前面几个 Sections 介绍了关于 Django 请求(Request)处理的流程分析,我们也了解到,Django 是围绕着 Request 与 Respon ...

  10. python 视图 (FBV、CBV ) 、Request 和Response对象 、路由系统

    一.FBV和CBV1.基于函数的view,就叫FBV(Function Based View) 示例: def add_book(request): pub_obj=models.Publisher. ...

随机推荐

  1. js判断iPhone XS、iPhone XS Max、iPhone XR

    // iPhone X.iPhone XS && window.screen.width === && window.screen.height === ; // iP ...

  2. Making every developer more productive with Visual Studio 2019

    Today, in the Microsoft Connect(); 2018 keynote, Scott Guthrie announced the availability of Visual ...

  3. a标签 download base64 下载 网络失败

    使用html2canvas 生成尺寸较大 base64 后进行 a标签  download 下载 ,浏览器报网络失败错误 通过谷歌搜索 发现原因是 因为截取尺寸较大  导致生成base64 长度太大 ...

  4. 【THUSC2017】【LOJ2978】杜老师 高斯消元

    题目大意 给你 \(l,r\),求从 \(l\) 到 \(r\) 这 \(r-l+1\) 个数中能选出多少个不同的子集,满足子集中所有的数的乘积是一个完全平方数. 对 \(998244353\) 取模 ...

  5. VBScript 学习笔记

    创建一个变量 VBScript 变量名称的规则: 必须以字母开头 不能包含点号(.) 不能超过 255 个字符 在 VBScript 的缩写中,所有的变量都与类型 variant 相关,可存储不同类型 ...

  6. Mysql 查询当月时间数据

    SELECTDATE_FORMAT(CURDATE(), '%Y%m'), DATE_FORMAT(t.transactiontime, '%Y%m'),t.*FROM ttransactions t ...

  7. visual studio 中sstrcpy报错的问题

    项目->属性->C/C++->预处理器->预处理器定义->添加 _CRT_SECURE_NO_WARNINGS

  8. showdoc app接口文档编写利器

    通过朋友介绍,才知道有这么好的一个在线接口编写文档开源项目,非常感谢原作者的贡献 ShowDoc介绍 关于ShowDoc的介绍,请访问:http://blog.star7th.com/2015/11/ ...

  9. 关于std::cin阻塞事件循环以及控制台命令输入功能的方案;

    如果将std::cin建立在主线程,将阻塞主线程的所有事件循环,因而要保证事件循环不受影响,需要将std::cin放到 子线程中.同时,如果要实现能够强制终止std::cin阻塞, 可以通过强制终止线 ...

  10. com.alibaba.druid数据源工具类

    Druid是阿里巴巴推出的国产数据库连接池,据网上测试对比,比目前的DBCP或C3P0数据库连接池性能更好.它不仅仅是一个数据库连接池,它还包含一个ProxyDriver,一系列内置的JDBC组件库, ...