请求和响应对象¶
快速概述¶
Django 使用请求和响应对象在系统中传递状态。
当一个页面被请求时,Django 会创建一个 HttpRequest
对象,这个对象包含了请求的元数据。然后,Django 加载相应的视图,将 HttpRequest
作为视图函数的第一个参数。每个视图负责返回一个 HttpResponse
对象。
本文档解释了 django.http
模块中定义的 HttpRequest
和 HttpResponse
对象的 API。
HttpRequest
对象¶
属性¶
除非另有说明,否则所有属性都应视为只读。
-
HttpRequest.
body
[源代码]¶ 原始的 HTTP 请求体作为一个字节字符串。这对于以不同方式处理非常规 HTML 表单的数据很有用:二进制图像,XML 有效负载等。对于处理传统的表单数据,使用
HttpRequest.POST
。你也可以使用类似文件的接口
HttpRequest.read()
或HttpRequest.readline()
从HttpRequest
中读取。在使用这些 I/O 流方法中的任何一种方法读取请求后,访问body
属性会产生RawPostDataException
。
-
HttpRequest.
path
¶ 一个表示请求页面的完整路径的字符串,不包括 scheme、域名或查询字符串。
例如:
"/music/bands/the_beatles/"
-
HttpRequest.
path_info
¶ 在某些 Web 服务器配置下,主机名后面的 URL 部分被分成脚本前缀部分和路径信息部分。无论使用哪个 Web 服务器,
path_info
属性始终包含路径信息部分。使用这个属性而不是path
可以使您的代码更容易在测试和部署服务器之间移动。例如,如果你的应用程序的
WSGIScriptAlias
设置为"/minfo"
,那么path
可能是"/minfo/music/bands/the_beatles/"
和path_info
将是"/music/bands/the_beatles/"
。
-
HttpRequest.
method
¶ 代表请求中使用的 HTTP 方法的字符串。保证是大写字母。例如:
if request.method == "GET": do_something() elif request.method == "POST": do_something_else()
-
HttpRequest.
encoding
[源代码]¶ 表示当前用于解码表单提交数据的编码的字符串(或
None
,表示使用DEFAULT_CHARSET
设置)。你可以写入这个属性来改变访问表单数据时使用的编码。任何后续的属性访问(如从GET
或POST
中读取)将使用新的encoding
值。如果你知道表单数据不是在DEFAULT_CHARSET
编码中,这很有用。
-
HttpRequest.
content_type
¶ 代表请求的 MIME 类型的字符串,从
CONTENT_TYPE
头解析。
-
HttpRequest.
content_params
¶ CONTENT_TYPE
头中包含的键/值参数字典。
-
HttpRequest.
POST
¶ 一个类似字典的对象,包含所有给定的 HTTP POST 参数,前提是请求包含表单数据。参见下面的
QueryDict
文档。如果你需要访问请求中发布的原始或非表单数据,可以通过HttpRequest.body
属性来访问。有可能一个请求是通过 POST 方式进来的,并带有一个空的
POST
字典——比如说,一个表单是通过 POST HTTP 方法请求的,但不包括表单数据。因此,你不应该使用if request.POST
来检查是否使用了 POST 方法;而应该使用if request.method == "POST"
(参见HttpRequest.method
)。POST
不包括文件上传信息。见FILES
。
-
HttpRequest.
COOKIES
¶ 一个包含所有 cookies 的字典。键和值是字符串。
-
HttpRequest.
FILES
¶ 一个类似字典的对象,包含所有上传的文件。
FILES
中的每个键是<input type="file" name="">
中的name
。FILES
中的每个值是一个UploadedFile
。更多信息请参见 管理文件。
FILES
只有在请求方法是 POST,并且发布请求的<form>
有enctype="multipart/form-data"
的情况下,才会包含数据。否则,FILES
将是一个类似字典的空白对象。
-
HttpRequest.
META
¶ 一个包含所有可用的 HTTP 头文件的字典。可用的头信息取决于客户端和服务器,但这里有一些例子:
CONTENT_LENGTH
—— 请求体的长度(字符串)。CONTENT_TYPE
—— 请求体的 MIME 类型。HTTP_ACCEPT
—— 可接受的响应内容类型。HTTP_ACCEPT_ENCODING
—— 可接受的响应编码。HTTP_ACCEPT_LANGUAGE
—— 可接受的响应语言。HTTP_HOST
—— 客户端发送的 HTTP 主机头。HTTP_REFERER
—— referrer 页面,如果有的话。HTTP_USER_AGENT
—— 客户端的用户代理字符串。QUERY_STRING
—— 查询字符串,是一个单一的(未解析的)字符串。REMOTE_ADDR
—— 客户机的 IP 地址。REMOTE_HOST
—— 客户机的主机名。REMOTE_USER
-- 如果有的话,由 Web 服务器进行身份验证的用户。REQUEST_METHOD
——"GET"
或"POST"
等字符串。SERVER_NAME
—— 服务器的主机名。SERVER_PORT
—— 服务器的端口(字符串)。
除了上面给出的
CONTENT_LENGTH
和CONTENT_TYPE
之外,请求中的任何 HTTP 头都会被转换为META
键,方法是将所有字符转换为大写字母,用下划线代替任何连字符,并在名称前加上HTTP_`
前缀。因此,例如,一个名为X-Bender
的头将被映射到META
键HTTP_X_BENDER
。请注意,
runserver
会删除名称中带有下划线的所有标头,因此您不会在META
中看到它们。这可以防止基于下划线和破折号之间的模糊性而进行标头欺骗,因为在 WSGI 环境变量中,它们都会被规范化为下划线。这与像 Nginx 和 Apache 2.4+ 这样的 Web 服务器的行为相匹配。HttpRequest.headers
是一种更简单的方式来访问所有 HTTP 前缀头,加上CONTENT_LENGTH
和CONTENT_TYPE
。
-
HttpRequest.
headers
[源代码]¶ 一个不区分大小写的类似字典的对象,提供对请求中所有 HTTP 前缀头的访问(加上
Content-Length
和Content-Type
)。每个标头的名称在显示时以标题大小写形式呈现(例如,
User-Agent
)。您可以不区分大小写地访问标头:>>> request.headers {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6', ...} >>> "User-Agent" in request.headers True >>> "user-agent" in request.headers True >>> request.headers["User-Agent"] Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) >>> request.headers["user-agent"] Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) >>> request.headers.get("User-Agent") Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) >>> request.headers.get("user-agent") Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)
例如,在 Django 模板中,还可以使用下划线代替连字符来查找标头:
{{ request.headers.user_agent }}
-
HttpRequest.
resolver_match
¶ ResolverMatch
的一个实例,代表解析后的 URL。这个属性只有在 UR L解析发生后才会被设置,这意味着它在所有的视图中都是可用的,但在 URL 解析发生前被执行的中间件中则不可用(不过你可以在process_view()
中使用它)。
应用程序代码设置的属性¶
Django 不会自己设置这些属性,但如果你的应用程序设置了这些属性,就会使用它们。
-
HttpRequest.
urlconf
¶ 这将作为当前请求的根 URLconf,覆盖
ROOT_URLCONF
设置。详情请参见 Django 如何处理一个请求。urlconf
可以设置为None
,以恢复之前中间件所做的任何更改,并返回到使用ROOT_URLCONF
。
-
HttpRequest.
exception_reporter_filter
¶ 这将代替当前请求的
DEFAULT_EXCEPTION_REPORTER_FILTER
使用。详情请参见 自定义错误报告。
-
HttpRequest.
exception_reporter_class
¶ 这将代替
DEFAULT_EXCEPTION_REPORTER
用于当前请求。详情请参见 自定义错误报告。
中间件设置的属性¶
Django 的 contrib 应用中包含的一些中间件会在请求中设置属性。如果你没有在请求中看到属性,请确认在 MIDDLEWARE
中列出了相应的中间件类。
-
HttpRequest.
session
¶ 来自
SessionMiddleware
。一个可读可写的,类似字典的对象,代表当前会话。
-
HttpRequest.
site
¶ 来自
CurrentSiteMiddleware
。由Site()
或RequestSite
返回的get_current_site()
的实例,代表当前站点。
-
HttpRequest.
user
¶ 从
AuthenticationMiddleware
。AUTH_USER_MODEL
的一个实例,代表当前登录的用户。如果用户当前没有登录,user
将被设置为一个AnonymousUser
的实例。你可以用is_authenticated
来区分它们,比如:if request.user.is_authenticated: ... # Do something for logged-in users. else: ... # Do something for anonymous users.
auser()
方法执行相同的操作,但可以从异步上下文中使用。
方法¶
-
HttpRequest.
auser
()¶ - New in Django 5.0.
从
AuthenticationMiddleware
中的协程。返回一个表示当前已登录用户的AUTH_USER_MODEL
实例。如果用户当前未登录,auser
将返回AnonymousUser
的实例。这类似于user
属性,但它在异步上下文中工作。
-
HttpRequest.
get_host
()[源代码]¶ 使用
HTTP_X_FORWARDED_HOST
(如果USE_X_FORWARDED_HOST
已启用)和HTTP_HOST
头信息,按顺序返回请求的发起主机。如果它们没有提供一个值,则该方法使用SERVER_NAME
和SERVER_PORT
的组合,详见 PEP 3333。例如:
"127.0.0.1:8000"
如果主机不在
ALLOWED_HOSTS
中或者域名根据 RFC 1034/RFC 1035 无效,则引发django.core.exceptions.DisallowedHost
异常。备注
get_host()
方法在主机处于多个代理后面时失效。一个解决方案是使用中间件重写代理头,如下面的例子:class MultipleProxyMiddleware: FORWARDED_FOR_FIELDS = [ "HTTP_X_FORWARDED_FOR", "HTTP_X_FORWARDED_HOST", "HTTP_X_FORWARDED_SERVER", ] def __init__(self, get_response): self.get_response = get_response def __call__(self, request): """ Rewrites the proxy headers so that only the most recent proxy is used. """ for field in self.FORWARDED_FOR_FIELDS: if field in request.META: if "," in request.META[field]: parts = request.META[field].split(",") request.META[field] = parts[-1].strip() return self.get_response(request)
这个中间件应该定位在任何其他依赖于:meth:~HttpRequest.get_host() 值的中间件之前——例如
CommonMiddleware
或CsrfViewMiddleware
。
-
HttpRequest.
get_port
()[源代码]¶ 使用
HTTP_X_FORWARDED_PORT
(如果 :set:`USE_X_FORWARDED_PORT` 已启用)和SERVER_PORT
META
变量中的信息,按顺序返回请求的起始端口。
-
HttpRequest.
get_full_path
()[源代码]¶ 返回
path
,加上附加的查询字符串(如果适用)。例如:
"/music/bands/the_beatles/?print=true"
-
HttpRequest.
get_full_path_info
()[源代码]¶ 像
get_full_path()
一样,但使用path_info
代替path
。例如:
"/minfo/music/bands/the_beatles/?print=true"
-
HttpRequest.
build_absolute_uri
(location=None)[源代码]¶ 返回
location
的绝对 URI 形式。如果没有提供 location,location 将被设置为request.get_full_path()
。如果 location 已经是一个绝对 URI,它将不会被改变。否则,绝对 URI 将使用这个请求中可用的服务器变量建立。例如:
>>> request.build_absolute_uri() 'https://example.com/music/bands/the_beatles/?print=true' >>> request.build_absolute_uri("/bands/") 'https://example.com/bands/' >>> request.build_absolute_uri("https://example2.com/bands/") 'https://example2.com/bands/'
备注
在同一站点上混合使用 HTTP 和 HTTPS 是不鼓励的,因此
build_absolute_uri()
将始终生成与当前请求具有相同协议的绝对 URI。如果您需要将用户重定向到 HTTPS,请最好让您的 Web 服务器将所有 HTTP 流量重定向到 HTTPS。
-
HttpRequest.
get_signed_cookie
(key, default=RAISE_ERROR, salt='', max_age=None)[源代码]¶ 返回已签名 cookie 的 cookie 值,如果签名不再有效,则会引发
django.core.signing.BadSignature
异常。如果你提供了default
参数,异常将被抑制,并返回默认值。可选的
salt
参数可以用来提供额外的保护,以防止对你秘钥的暴力攻击。如果提供了这个参数,max_age
参数将根据附加在 cookie 值上的签名时间戳进行检查,以确保 cookie 不超过max_age
秒。例如:
>>> request.get_signed_cookie("name") 'Tony' >>> request.get_signed_cookie("name", salt="name-salt") 'Tony' # assuming cookie was set using the same salt >>> request.get_signed_cookie("nonexistent-cookie") KeyError: 'nonexistent-cookie' >>> request.get_signed_cookie("nonexistent-cookie", False) False >>> request.get_signed_cookie("cookie-that-was-tampered-with") BadSignature: ... >>> request.get_signed_cookie("name", max_age=60) SignatureExpired: Signature age 1677.3839159 > 60 seconds >>> request.get_signed_cookie("name", False, max_age=60) False
更多信息请参见 加密签名。
-
HttpRequest.
accepts
(mime_type)[源代码]¶ 如果请求的
Accept
标头与mime_type
参数匹配,则返回True
:>>> request.accepts("text/html") True
大多数浏览器默认发送
Accept: */*
,默认情况下,这将为所有内容类型返回True
。在 API 请求中设置一个显式的Accept
头,对于只为那些消费者返回不同的内容类型是很有用的。参见 内容协商示例 使用accepts()
向 API 消费者返回不同的内容。如果一个响应根据
Accept
头的内容而变化,并且你使用了某种形式的缓存,比如 Django 的cache middleware
,你应该用vary_on_headers('Accept')
来装饰视图,这样响应就会被正确地缓存。
-
HttpRequest.
__iter__
()[源代码]¶ 实现从
HttpRequest
实例中读取文件的类似接口的方法。这使得它可以以流式方式处理一个传入的请求。一个常见的用例是用迭代解析器处理一个大的 XML 有效载荷,而无需在内存中构建一个完整的 XML 树。给定这个标准接口,一个
HttpRequest
实例可以直接传递给 XML 解析器,如ElementTree
:import xml.etree.ElementTree as ET for element in ET.iterparse(request): process(element)
QueryDict
对象¶
在一个 HttpRequest
对象中, GET
和 POST
属性是 django.http.QueryDict
的实例,这是一个类似字典的类,用来处理同一个键的多个值。这是很有必要的,因为一些 HTML 表单元素,尤其是 <select multiple>
,会传递同一个键的多个值。
在 request.POST
和 request.GET
中的 QueryDict
将在正常的请求/响应周期中被访问时是不可改变的。要得到一个可变的版本,你需要使用 QueryDict.copy()
。
方法¶
QueryDict
实现了所有标准的字典方法,因为它是字典的一个子类。这里概述了例外情况:
-
QueryDict.
__init__
(query_string=None, mutable=False, encoding=None)[源代码]¶ 基于
query_string
实例化一个QueryDict
对象。>>> QueryDict("a=1&a=2&c=3") <QueryDict: {'a': ['1', '2'], 'c': ['3']}>
如果没有传入
query_string
,产生的QueryDict
将是空的(它将没有键或值)。你遇到的大多数
QueryDict
s,特别是那些在request.POST
和request.GET
的,将是不可变的。如果你自己实例化一个,你可以通过传递mutable=True
到它的__init__()
来使它可变。设置键和值的字符串将从
encoding
转换为str
。如果没有设置encoding
,则默认为DEFAULT_CHARSET
。
-
classmethod
QueryDict.
fromkeys
(iterable, value='', mutable=False, encoding=None)[源代码]¶ 使用来自
iterable
的键和每个值等于value
的值创建一个新的QueryDict
。例如:>>> QueryDict.fromkeys(["a", "a", "b"], value="val") <QueryDict: {'a': ['val', 'val'], 'b': ['val']}>
-
QueryDict.
__getitem__
(key)¶ 返回给定键的值。如果键有多个值,则返回最后一个值。如果键不存在,会引发
django.utils.datastructures.MultiValueDictKeyError
。(这是 Python 标准的KeyError
的一个子类,所以你可以坚持捕捉KeyError
。)
-
QueryDict.
__setitem__
(key, value)[源代码]¶ 将给定的键设置为
[value]
(一个单一元素为value
的列表)。请注意,这个函数和其他有副作用的字典函数一样,只能在一个可变的QueryDict
上调用(比如通过QueryDict.copy()
创建的)。
-
QueryDict.
__contains__
(key)¶ 如果给定的键被设置,返回
True
。这让你可以执行,例如,if "foo" in request.GET
。
-
QueryDict.
get
(key, default=None)¶ 使用与
__getitem__()
相同的逻辑,如果键不存在,则用钩子返回一个默认值。
-
QueryDict.
setdefault
(key, default=None)[源代码]¶ 与
dict.setdefault()
一样,只是它在内部使用__setitem__()
。
-
QueryDict.
update
(other_dict)¶ 接受一个
QueryDict
或一个字典。类似于dict.update()
,但它会将项目添加到当前字典而不是替换它们。例如:>>> q = QueryDict("a=1", mutable=True) >>> q.update({"a": "2"}) >>> q.getlist("a") ['1', '2'] >>> q["a"] # returns the last '2'
-
QueryDict.
items
()¶ 类似于
dict.items()
,不过它使用与__getitem__()
相同的最后一个值逻辑,并返回一个迭代器对象而不是视图对象。例如:>>> q = QueryDict("a=1&a=2&a=3") >>> list(q.items()) [('a', '3')]
-
QueryDict.
values
()¶ 类似于
dict.values()
,不过它使用与__getitem__()
相同的最后一个值逻辑,并返回一个迭代器而不是视图对象。例如:>>> q = QueryDict("a=1&a=2&a=3") >>> list(q.values()) ['3']
此外,QueryDict
有以下方法:
-
QueryDict.
copy
()[源代码]¶ 使用
copy.deepcopy()
返回对象的副本。这个副本将是可变的,即使原始副本不是。
-
QueryDict.
getlist
(key, default=None)¶ 返回带有请求键的数据列表。如果键不存在且
default
是None
,则返回一个空列表。除非提供的默认值不是一个列表,否则保证返回一个列表。
-
QueryDict.
setlist
(key, list_)[源代码]¶ 将给定的键设置为
list_
(与__setitem__()
不同)。
-
QueryDict.
setlistdefault
(key, default_list=None)[源代码]¶ 和
setdefault()
一样,只不过它取的是一个值的列表,而不是单个值。
-
QueryDict.
lists
()¶ 类似于
items()
,不过它包括字典中每个成员的所有值,以列表的形式。例如:>>> q = QueryDict("a=1&a=2&a=3") >>> q.lists() [('a', ['1', '2', '3'])]
-
QueryDict.
pop
(key)[源代码]¶ 返回给定键的值列表并从字典中删除它们。如果键不存在,则引发
KeyError
。例如:>>> q = QueryDict("a=1&a=2&a=3", mutable=True) >>> q.pop("a") ['1', '2', '3']
-
QueryDict.
popitem
()[源代码]¶ 移除字典中的一个任意成员(因为没有顺序概念),并返回一个包含键和该键所有值的列表的两个值的元组。当在空字典上调用时,引发
KeyError
。例如:>>> q = QueryDict("a=1&a=2&a=3", mutable=True) >>> q.popitem() ('a', ['1', '2', '3'])
-
QueryDict.
dict
()¶ 返回
QueryDict
的dict
表示。对于QueryDict
中的每个(键,列表)对,dict
将具有(键,项),其中项是列表的一个元素,使用与QueryDict.__getitem__()
相同的逻辑:>>> q = QueryDict("a=1&a=3&a=5") >>> q.dict() {'a': '5'}
HttpResponse
对象¶
与 Django 自动创建的 HttpRequest
对象不同, HttpResponse
对象是你的责任。你写的每个视图都要负责实例化、填充和返回一个 HttpResponse
对象。
HttpResponse
类位于 django.http
模块中。
用法¶
传入字符串¶
典型的用法是将页面的内容作为字符串、字节串或 memoryview
传递给 HttpResponse
构造函数:
>>> from django.http import HttpResponse
>>> response = HttpResponse("Here's the text of the web page.")
>>> response = HttpResponse("Text only, please.", content_type="text/plain")
>>> response = HttpResponse(b"Bytestrings are also accepted.")
>>> response = HttpResponse(memoryview(b"Memoryview as well."))
但如果你想逐步添加内容,你可以将 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
将立即消耗迭代器,将其内容存储为一个字符串,然后丢弃它。带有 close()
方法的对象,如文件和生成器,会立即关闭。
如果你需要将响应从迭代器流式传输到客户端,你必须使用 StreamingHttpResponse
类来代替。
设置头字段¶
要在响应中设置或移除头字段,使用 HttpResponse.headers
:
>>> response = HttpResponse()
>>> response.headers["Age"] = 120
>>> del response.headers["Age"]
你还可以通过将响应当作字典来操作头部信息:
>>> response = HttpResponse()
>>> response["Age"] = 120
>>> del response["Age"]
这相当于代理到了 HttpResponse.headers
,也是 HttpResponse
最初提供的接口。
使用这个接口时,不像字典那样,如果头字段不存在,del
不会引发 KeyError
。
你还可以在实例化时设置头部信息:
>>> response = HttpResponse(headers={"Age": 120})
对于设置 Cache-Control
和 Vary
头字段,建议使用 django.utils.cache.patch_cache_control
和 django.utils.cache.patch_vary_headers
中的 patch_cache_control()
和 patch_vary_headers()
方法,因为这些字段可以有多个以逗号分隔的值。这些“补丁”方法保证了其他的值,例如由中间件添加的值,不会被删除。
HTTP 头字段不能包含换行符。试图设置一个包含换行符(CR 或 LF)的头字段将引发 BadHeaderError
。
告诉浏览器将响应作为文件附件处理¶
要告诉浏览器将响应视为文件附件,设置 Content-Type
和 Content-Disposition
头部。例如,这是如何返回一个 Microsoft Excel 电子表格的方式:
>>> response = HttpResponse(
... my_data,
... headers={
... "Content-Type": "application/vnd.ms-excel",
... "Content-Disposition": 'attachment; filename="foo.xls"',
... },
... )
Content-Disposition
头并没有什么 Django 特有的内容,但是很容易忘记语法,所以我们把它包含在这里。
属性¶
-
HttpResponse.
cookies
¶ 一个包含在响应中的 cookie 的
http.cookies.SimpleCookie
对象。
-
HttpResponse.
headers
¶ 一个不区分大小写的、类似字典的对象,提供对响应中除了
Set-Cookie
头部之外的所有 HTTP 头部的接口。请参阅 设置头字段 和HttpResponse.cookies
。
-
HttpResponse.
charset
¶ 表示响应将被编码的字符集的字符串。如果在
HttpResponse
实例化时没有给出,将从content_type
中提取,如果不成功,将使用DEFAULT_CHARSET
设置。
-
HttpResponse.
status_code
¶ 响应的 HTTP 状态码。
除非
reason_phrase
被明确设置,否则在构造函数外修改status_code
的值也会修改reason_phrase
的值。
-
HttpResponse.
reason_phrase
¶ 响应的 HTTP 原因短语。它使用 HTTP 标准 中的默认原因短语。
除非明确设置,否则
reason_phrase
由status_code
的值决定。
-
HttpResponse.
streaming
¶ 这总是
False
。此属性的存在是为了让中间件能够将流式响应与常规响应区别对待。
-
HttpResponse.
closed
¶ True
如果响应已经结束。
方法¶
-
HttpResponse.
__init__
(content=b'', content_type=None, status=200, reason=None, charset=None, headers=None)[源代码]¶ 使用给定的页面内容、内容类型和头部实例化一个
HttpResponse
对象。content
最常见的是迭代器、字节字符串、memoryview
或字符串。其他类型将通过对它们的字符串表示进行编码而转换为字节组。迭代器应该返回字符串或字节字符串,这些将被连接在一起以形成响应的内容。content_type
是 MIME 类型,可选择用字符集编码完成,用于填充 HTTPContent-Type
头。如果没有指定,则由'text/html'
和DEFAULT_CHARSET
配置组成,默认情况下:"text/html; charset=utf-8"
。status
是响应的 HTTP 状态码。你可以使用 Python 的http.HTTPStatus
来使用有意义的别名,例如HTTPStatus.NO_CONTENT
。reason
是 HTTP 响应短语。如果没有提供,将使用默认短语。charset
是对响应进行编码的字符集。如果没有给出,将从content_type
中提取,如果不成功,将使用DEFAULT_CHARSET
配置。headers
是响应的 HTTP 头部的dict
。
-
HttpResponse.
__setitem__
(header, value)¶ 将给定的响应头名设置为给定的值。
header
和value
都应该是字符串。
-
HttpResponse.
__delitem__
(header)¶ 删除指定名称的响应头。如果头不存在,则静默失败。不区分大小写。
-
HttpResponse.
__getitem__
(header)¶ 返回给定响应头名的值。不区分大小写。
-
HttpResponse.
get
(header, alternate=None)¶ 返回给定响应头的值,如果头不存在,则返回
alternate
。
-
HttpResponse.
has_header
(header)¶ 根据对给定名称的响应头进行不区分大小写的检查,返回
True
或False
。
-
HttpResponse.
items
()¶ 像
dict.items()
一样作用于响应的 HTTP 头信息。
-
HttpResponse.
setdefault
(header, value)¶ 设置响应头,除非它已经被设置。
-
HttpResponse.
set_cookie
(key, value='', max_age=None, expires=None, path='/', domain=None, secure=False, httponly=False, samesite=None)¶ 设置一个 cookie。参数与 Python 标准库中的
Morsel
cookie 对象相同。max_age
应该是一个timedelta
对象、整数秒数,或者None
(默认值),如果 cookie 只应持续客户端浏览器会话的时间。如果未指定expires
,它将被计算。expires
应是格式为"Wdy, DD-Mon-YY HH:MM:SS GMT"
的字符串,或者是 UTC 的datetime.datetime
对象。如果expires
是一个datetime
对象,将计算max_age
。如果你想设置一个跨域的 cookie,请使用
domain
。例如,domain="example.com"
将设置一个可被 www.example.com、blog.example.com 等域读取的 cookie。否则,一个 cookie 将只能被设置它的域读取。如果你想让 cookie 只在使用
https
方案进行请求时才发送给服务器,请使用secure=True
。如果你想防止客户端的 JavaScript 访问 cookie,请使用
httponly=True
。HttpOnly 是包含在 Set-Cookie HTTP 响应头中的一个标志。它是 RFC 6265 标准中 Cookie 的一部分,可以作为一种有用的方式来降低客户端脚本访问受保护 Cookie 数据的风险。
使用
samesite='Strict'
或samesite='Lax'
来告诉浏览器在执行跨源请求时不要发送这个 cookie。SameSite 并不是所有浏览器都支持,所以它并不能替代 Django 的 CSRF 保护,而是一种深度防御措施。使用
samesite=''None'
(字符串)来明确说明这个 cookie 会随着所有的同站和跨站请求而发送。
警告
RFC 6265 规定,用户代理应支持至少 4096 字节的 cookies。对于很多浏览器来说,这也是最大的尺寸。如果试图存储一个超过 4096 字节的 cookie,Django 不会引发异常,但很多浏览器不会正确设置 cookie。
-
HttpResponse.
set_signed_cookie
(key, value, salt='', max_age=None, expires=None, path='/', domain=None, secure=False, httponly=False, samesite=None)¶ 像
set_cookie()
一样,但是 在设置 cookie 之前对它进行加密签名。与HttpRequest.get_signed_cookie()
一起使用。你可以使用可选的salt
参数来增加密钥强度,但你需要记得把它传递给相应的HttpRequest.get_signed_cookie()
调用。
-
HttpResponse.
delete_cookie
(key, path='/', domain=None, samesite=None)¶ 删除给定键的 cookie。如果键不存在,则静默失败。
由于 cookie 的工作方式,
path
和domain
应该与你在set_cookie()
中使用的值相同,否则 cookie 可能不会被删除。
-
HttpResponse.
close
()¶ 本方法在请求结束时由 WSGI 服务器直接调用。
-
HttpResponse.
write
(content)[源代码]¶ 这个方法使一个
HttpResponse
实例成为一个类似文件的对象。
-
HttpResponse.
flush
()¶ 这个方法使一个
HttpResponse
实例成为一个类似文件的对象。
-
HttpResponse.
tell
()[源代码]¶ 这个方法使一个
HttpResponse
实例成为一个类似文件的对象。
-
HttpResponse.
getvalue
()[源代码]¶ 返回
HttpResponse.content
的值。本方法使一个 :class:`HttpResponse`实例成为一个类流对象。
-
HttpResponse.
readable
()¶ 总是
False
。此方法使HttpResponse
实例成为一个类流对象。
-
HttpResponse.
seekable
()¶ 总是
False
。此方法使HttpResponse
实例成为一个类流对象。
-
HttpResponse.
writable
()[源代码]¶ 总是
True
。此方法使HttpResponse
实例成为一个类流对象。
-
HttpResponse.
writelines
(lines)[源代码]¶ 将行的列表写入响应。不添加行的分隔符。此方法使
HttpResponse
实例成为一个类流对象。
HttpResponse
子类¶
Django 包含了许多 HttpResponse
的子类来处理不同类型的 HTTP 响应。像 HttpResponse
一样,这些子类位于 django.http
中。
-
class
HttpResponseRedirect
[源代码]¶ 构造函数的第一个参数是必需的——要重定向的路径。这可以是一个完全限定的 URL(例如
'https://www.yahoo.com/search/
),一个没有域名的绝对路径(例如'/search/'
),甚至是一个相对路径(例如'search/'
)。在最后一种情况下,客户端浏览器会根据当前路径自己重建完整的 URL。参见HttpResponse
了解其他可选的构造函数参数。请注意,这将返回一个 HTTP 状态码 302。-
url
¶ 这个只读属性表示响应将重定向到的 URL(相当于
Location
响应头)。
-
-
class
HttpResponsePermanentRedirect
[源代码]¶ 就像
HttpResponseRedirect
一样,但它返回的是一个永久重定向(HTTP 状态码 301),而不是“found”重定向(状态码 302)。
-
class
HttpResponseBadRequest
[源代码]¶ 就像
HttpResponse
一样,但使用 400 状态码。
-
class
HttpResponseNotFound
[源代码]¶ 就像
HttpResponse
一样,但使用 404 状态码。
-
class
HttpResponseForbidden
[源代码]¶ 就像
HttpResponse
一样,但使用 403 状态码。
-
class
HttpResponseNotAllowed
[源代码]¶ 就像
HttpResponse
一样,但使用 405 状态码。构造函数的第一个参数是必需的:一个允许的方法列表(例如['GET', 'POST']
)。
-
class
HttpResponseGone
[源代码]¶ 就像
HttpResponse
一样,但使用 410 状态码。
-
class
HttpResponseServerError
[源代码]¶ 就像
HttpResponse
一样,但使用 500 状态码。
备注
如果 HttpResponse
的自定义子类实现了 render
方法,Django 会将其视为模拟 SimpleTemplateResponse
,并且 render
方法本身必须返回一个有效的响应对象。
自定义响应类¶
如果你发现自己需要一个 Django 没有提供的响应类,你可以借助 http.HTTPStatus
来创建它。例如:
from http import HTTPStatus
from django.http import HttpResponse
class HttpResponseNoContent(HttpResponse):
status_code = HTTPStatus.NO_CONTENT
JsonResponse
对象¶
-
class
JsonResponse
(data, encoder=DjangoJSONEncoder, safe=True, json_dumps_params=None, **kwargs)[源代码]¶ 一个
HttpResponse
子类,帮助创建一个 JSON 编码的响应。它继承了它的超类的大部分行为,但有一些不同:其默认的
Content-Type
头设置为 application/json。第一个参数
data
应该是dict
实例。如果safe
参数设置为False
(见下文),它可以是任何 JSON 可序列化的对象。encoder
,默认为django.core.serializers.json.DjangoJSONEncoder
,将用于序列化数据。关于这个序列化器的更多细节,请参见 JSON 序列化。safe
布尔参数默认为True
。如果它被设置为False
,任何对象都可以被传递到序列化中(否则只允许dict
实例)。如果safe
为True
,而第一个参数是一个非dict
对象,则会引发一个TypeError
。json_dumps_params
参数是一个关键字参数的字典,用来传递给json.dumps()
调用,用于生成响应。
用法¶
典型的用法可能如下所示:
>>> from django.http import JsonResponse
>>> response = JsonResponse({"foo": "bar"})
>>> response.content
b'{"foo": "bar"}'
序列化非字典对象¶
为了序列化除了 dict
之外的对象,你必须将 safe
参数设置为 False
:
>>> response = JsonResponse([1, 2, 3], safe=False)
如果没有传递 safe=False
,将引发一个 TypeError
。
注意,基于 dict
对象的 API 更具可扩展性、灵活性,并且更容易维护前向兼容性。因此,你应该避免在 JSON 编码的响应中使用非字典对象。
警告
在 ECMAScript 第 5 版 之前,可能会对 JavaScript 的 Array
构造函数进行恶意操作。因此,Django 默认情况下不允许将非字典对象传递给 JsonResponse
构造函数。然而,大多数现代浏览器实现了 ECMAScript 5,消除了这种攻击方式。因此,可以禁用这个安全预防措施。
更改默认 JSON 编码器¶
如果你需要使用不同的 JSON 编码器类,可以将 encoder
参数传递给构造方法:
>>> response = JsonResponse(data, encoder=MyJSONEncoder)
StreamingHttpResponse
对象¶
StreamingHttpResponse
类用于从 Django 向浏览器流式传输响应。
StreamingHttpResponse
在 WSGI 下的一个示例用法是在生成响应时需要太长时间或使用太多内存的情况下进行流式传输内容。例如,在 生成大型 CSV 文件 时非常有用。
不过,在执行这种操作时需要考虑性能问题。Django 在 WSGI 下设计用于短暂的请求。流式响应将绑定一个工作进程在响应的整个持续时间内。这可能导致性能不佳。
一般来说,你应该在请求-响应周期之外执行昂贵的任务,而不是采用流式响应。
然而,在 ASGI 下提供服务时,一个 StreamingHttpResponse
不需要在等待 I/O 时阻止其他请求被处理。这打开了在流式传输内容时进行长时间请求和实施长轮询以及服务器推送事件等模式的可能性。
即使在 ASGI 下,也应该只在绝对需要在将数据传输给客户端之前不迭代整个内容的情况下使用 StreamingHttpResponse
。因为无法访问内容,许多中间件无法正常工作。例如,对于流式响应,无法生成 ETag
和 Content-Length
头部。
StreamingHttpResponse
不是 HttpResponse
的子类,因此它的 API 略有不同。然而,它几乎是相同的,但有以下显著的区别。
它应该被提供一个产生字节串、
memoryview
或字符串作为内容的迭代器。在 WSGI 下提供服务时,这应该是一个同步迭代器。在 ASGI 下提供服务时,应该是一个异步迭代器。除非迭代响应对象本身,否则无法访问其内容。这只应该在响应返回给客户端时发生:你不应该自己迭代响应。
在 WSGI 下,响应将同步迭代。在 ASGI 下,响应将异步迭代。(这就是为什么迭代器类型必须与你使用的协议匹配的原因。)
为了避免崩溃,迭代时将将不正确的迭代器类型映射到正确的类型,并引发警告,但为了执行这个操作,迭代器必须被完全消耗,这就破坏了使用
StreamingHttpResponse
的目的。它没有
content
属性。相反,它有一个streaming_content
属性。这可以在中间件中用于包装响应可迭代对象,但不应该被消耗。你不能使用类文件对象的
tell()
或write()
方法。这样做会引起一个异常。
HttpResponseBase
基类在 HttpResponse
和 StreamingHttpResponse
之间是通用的。
属性¶
-
StreamingHttpResponse.
streaming_content
[源代码]¶ 响应内容的迭代器,根据
HttpResponse.charset
编码的字节字符串。
-
StreamingHttpResponse.
status_code
¶ 响应的 HTTP 状态码。
除非
reason_phrase
被明确设置,否则在构造函数外修改status_code
的值也会修改reason_phrase
的值。
-
StreamingHttpResponse.
reason_phrase
¶ 响应的 HTTP 原因短语。它使用 HTTP 标准 中的默认原因短语。
除非明确设置,否则
reason_phrase
由status_code
的值决定。
-
StreamingHttpResponse.
streaming
¶ 这总是
True
。
-
StreamingHttpResponse.
is_async
¶ 一个布尔值,指示
StreamingHttpResponse.streaming_content
是否是异步迭代器。这对于需要包装
StreamingHttpResponse.streaming_content
的中间件非常有用。
处理断开连接¶
如果在流式响应期间客户端断开连接,Django 将取消处理响应的协程。如果你想手动清理资源,可以通过捕获 asyncio.CancelledError
来实现:
async def streaming_response():
try:
# Do some work here
async for chunk in my_streaming_iterator():
yield chunk
except asyncio.CancelledError:
# Handle disconnect
...
raise
async def my_streaming_view(request):
return StreamingHttpResponse(streaming_response())
这个示例只展示了在响应流式传输时如何处理客户端断开连接。如果在返回 StreamingHttpResponse
对象之前在视图中执行长时间运行的操作,那么你可能还想在视图本身中处理断开连接,可以参考 在视图中处理断开连接。
FileResponse
对象¶
-
class
FileResponse
(open_file, as_attachment=False, filename='', **kwargs)[源代码]¶ FileResponse
是StreamingHttpResponse
的一个子类,它针对二进制文件进行了优化。如果 wsgi 服务器提供的话,它使用 wsgi.file_wrapper,否则它将文件以小块的形式流式传输出去。如果
as_attachment=True
,Content-Disposition
头被设置为attachment
,要求浏览器将文件作为下载文件提供给用户。否则,只有在有文件名的情况下,才会设置值为inline
的Content-Disposition
头(浏览器默认)。如果
open_file
没有名字,或者open_file
的名字不合适,可以使用filename
参数提供一个自定义的文件名。请注意,如果你传递了一个类似文件的对象,比如io.BytesIO
,你的任务是在把它传递给FileResponse
之前seek()`
。当可以从
open_file
的内容猜测到时,Content-Length
头部将自动设置。当可以从
filename
或open_file
的名称猜测到时,Content-Type
头部将自动设置。
FileResponse
接受任何具有二进制内容的文件类似对象,例如以二进制模式打开的文件,如下所示:
>>> from django.http import FileResponse
>>> response = FileResponse(open("myfile.png", "rb"))
该文件会自动关闭,所以不要用上下文管理器打开它。
在 ASGI 下使用
Python 的文件 API 是同步的。这意味着文件必须被完全消耗才能在 ASGI 下提供服务。
为了异步流式传输文件,你需要使用提供异步文件 API 的第三方包,例如 aiofiles。
HttpResponseBase
类¶
HttpResponseBase
类是所有 Django 响应共有的。它不应该直接用于创建响应,但在类型检查方面可能会有用。