请求和响应对象

快速概览

Django 使用请求和响应对象来传递系统状态。

当请求页面时,Django 会创建一个 HttpRequest 对象,其中包含有关请求的元数据。然后,Django 加载适当的视图,将 HttpRequest 作为第一个参数传递给视图函数。每个视图负责返回一个 HttpResponse 对象。

本文档说明了 HttpRequestHttpResponse 对象的 API,它们在 django.http 模块中定义。

HttpRequest 对象

class HttpRequest

属性

除非另有说明,否则所有属性都应视为只读。

HttpRequest.scheme

表示请求方案的字符串(通常为 httphttps)。

HttpRequest.body

原始 HTTP 请求正文作为字节串。这对于以不同于传统 HTML 表单的方式处理数据非常有用:二进制图像、XML 有效负载等。要处理传统表单数据,请使用 HttpRequest.POST

您还可以使用文件类似接口通过 HttpRequest.read()HttpRequest.readline()HttpRequest 中读取。在使用任一 I/O 流方法读取请求访问 body 属性将生成 RawPostDataException

HttpRequest.path

一个表示请求页面完整路径的字符串,不包括方案、域名或查询字符串。

示例:"/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 设置)的当前编码的字符串。您可以写入此属性以更改访问表单数据时使用的编码。任何后续属性访问(例如从 GETPOST 中读取)都将使用新的 encoding 值。如果您知道表单数据不在 DEFAULT_CHARSET 编码中,则此方法非常有用。

HttpRequest.content_type

表示请求的 MIME 类型的字符串,从 CONTENT_TYPE 标头中解析。

HttpRequest.content_params

包含在 CONTENT_TYPE 标头中的键/值参数的字典。

HttpRequest.GET

包含所有给定 HTTP GET 参数的类字典的对象。请参见下面的 QueryDict 文档。

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

包含所有 cookie 的字典。键和值都是字符串。

HttpRequest.FILES

包含所有已上传文件的类字典的对象。FILES 中的每个键都是 <input type="file" name=""> 中的 nameFILES 中的每个值都是 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 – 引用页(如果存在)。
  • HTTP_USER_AGENT – 客户端的用户代理字符串。
  • QUERY_STRING – 查询字符串,作为单个(未解析)字符串。
  • REMOTE_ADDR – 客户端的 IP 地址。
  • REMOTE_HOST – 客户端的主机名。
  • REMOTE_USER – 由 Web 服务器(如果存在)认证的用户。
  • REQUEST_METHOD – 字符串,例如 "GET""POST"
  • SERVER_NAME – 服务器的主机名。
  • SERVER_PORT – 服务器的端口(作为字符串)。

除了上面给出的 CONTENT_LENGTHCONTENT_TYPE 之外,请求中的任何 HTTP 标头都会转换为 META 键,方法是将所有字符转换为大写,用下划线替换任何连字符,并在名称前添加 HTTP_ 前缀。因此,例如,名为 X-Bender 的标头将映射到 METAHTTP_X_BENDER

请注意,runserver 会删除名称中带有下划线的标头,因此您不会在 META 中看到它们。这可以防止基于下划线和破折号在 WSGI 环境变量中都标准化为下划线的歧义进行标头欺骗。它与 Nginx 和 Apache 2.4+ 等 Web 服务器的行为相匹配。

HttpRequest.headers 是访问所有 HTTP 前缀标头(加上 CONTENT_LENGTHCONTENT_TYPE)的更简单方法。

HttpRequest.headers

一个不区分大小写的类似字典的对象,它提供对请求中所有 HTTP 前缀标头(加上 Content-LengthContent-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

表示已解析 URL 的 ResolverMatch 实例。此属性仅在 URL 解析完成后设置,这意味着它在所有视图中都可用,但在 URL 解析之前执行的中间件中不可用(不过,你可以在 process_view() 中使用它)。

由应用程序代码设置的属性

Django 本身不会设置这些属性,但如果你的应用程序设置了这些属性,Django 会使用它们。

HttpRequest.current_app

url 模板标记会将其值用作 reverse()current_app 参数。

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

来自 CurrentSiteMiddlewareSiteRequestSite 的实例,由 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()
Django 5.0 中的新增功能。

来自 AuthenticationMiddleware:协程。返回表示当前登录用户的 AUTH_USER_MODEL 实例。如果用户当前未登录,auser 将返回 AnonymousUser 实例。这类似于 user 属性,但它适用于异步上下文。

HttpRequest.get_host()

使用 HTTP_X_FORWARDED_HOST(如果 USE_X_FORWARDED_HOST 已启用)和 HTTP_HOST 标头中的信息返回请求的原始主机,按此顺序。如果它们未提供值,该方法将使用 SERVER_NAMESERVER_PORT 的组合,如 PEP 3333 中所述。

示例:"127.0.0.1:8000"

如果主机不在 ALLOWED_HOSTS 中,或域名根据 RFC 1034/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)

此中间件应位于依赖 get_host() 值的任何其他中间件之前,例如 CommonMiddlewareCsrfViewMiddleware

HttpRequest.get_port()

使用 HTTP_X_FORWARDED_PORT(如果 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 形式。如果没有提供位置,则位置将设置为 request.get_full_path()

如果位置已经是绝对 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。

返回签名 cookie 的 cookie 值,如果签名不再有效,则引发 django.core.signing.BadSignature 异常。如果你提供了 default 参数,则会抑制异常,并返回该默认值。

可选的 salt 参数可用于为你的密钥提供额外的暴力攻击保护。如果提供了,则会根据附加到 cookie 值的签名时间戳检查 max_age 参数,以确保 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.is_secure()

如果请求是安全的,则返回 True;也就是说,如果它是通过 HTTPS 发出的。

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.read(size=None)
HttpRequest.readline()
HttpRequest.readlines()
HttpRequest.__iter__()

用于从 HttpRequest 实例读取的类文件接口实现方法。这使得以流式方式使用传入请求成为可能。一个常见的用例是使用迭代解析器处理大型 XML 有效负载,而无需在内存中构建整个 XML 树。

鉴于此标准接口,HttpRequest 实例可以直接传递给 XML 解析器,例如 ElementTree

import xml.etree.ElementTree as ET

for element in ET.iterparse(request):
    process(element)

QueryDict 对象

class QueryDict

HttpRequest 对象中,GETPOST 属性是 django.http.QueryDict 的实例,这是一个类似于字典的类,经过定制以处理同一密钥的多个值。这是必需的,因为某些 HTML 表单元素(特别是 <select multiple>)会为同一密钥传递多个值。

在正常的请求/响应周期中访问时,request.POSTrequest.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,尤其是 request.POSTrequest.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)

返回请求键的数据列表。如果键不存在且defaultNone,则返回一个空列表。除非提供的默认值不是列表,否则保证返回一个列表。

QueryDict.setlist(key, list_)

将给定的键设置为list_(与__setitem__()不同)。

QueryDict.appendlist(key, item)

将一个项目追加到与键关联的内部列表中。

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()

返回 QueryDictdict 表示形式。对于 QueryDict 中的每个 (key, list) 对,dict 将具有 (key, item),其中 item 是列表的一个元素,使用与 QueryDict.__getitem__() 相同的逻辑

>>> q = QueryDict("a=1&a=3&a=5")
>>> q.dict()
{'a': '5'}
QueryDict.urlencode(safe=None)

返回查询字符串格式的数据字符串。例如

>>> q = QueryDict("a=2&b=3&b=5")
>>> q.urlencode()
'a=2&b=3&b=5'

使用 safe 参数传递不需要编码的字符。例如

>>> q = QueryDict(mutable=True)
>>> q["next"] = "/a&b/"
>>> q.urlencode(safe="/")
'next=/a%26b/'

HttpResponse 对象

class 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-ControlVary 标头字段,建议使用 patch_cache_control()patch_vary_headers() 方法,因为这些字段可以具有多个以逗号分隔的值。这些“patch”方法确保不会删除其他值,例如中间件添加的值。

HTTP 标头字段不能包含换行符。尝试设置包含换行符 (CR 或 LF) 的标头字段将引发 BadHeaderError

告诉浏览器将响应视为文件附件

要告诉浏览器将响应视为文件附件,请设置 Content-TypeContent-Disposition 标头。例如,以下是返回 Microsoft Excel 电子表格的方法

>>> response = HttpResponse(
...     my_data,
...     headers={
...         "Content-Type": "application/vnd.ms-excel",
...         "Content-Disposition": 'attachment; filename="foo.xls"',
...     },
... )

对于 Content-Disposition 标头,没有 Django 特定的内容,但很容易忘记语法,因此我们在此处包含了它。

属性

HttpResponse.content

一个字节串,表示内容,必要时从字符串编码。

HttpResponse.cookies

一个 http.cookies.SimpleCookie 对象,包含响应中包含的 cookie。

HttpResponse.headers

一个不区分大小写的类似字典的对象,提供对响应中所有 HTTP 头的接口,除了 Set-Cookie 头。请参阅 设置头字段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_phrasestatus_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 类型,可选地由字符集编码完成,用于填充 HTTP Content-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 是一个 dict,用于响应的 HTTP 标头。

HttpResponse.__setitem__(header, value)

将给定的标头名称设置为给定的值。headervalue 都应该是字符串。

HttpResponse.__delitem__(header)

删除具有给定名称的标头。如果标头不存在,则静默失败。不区分大小写。

HttpResponse.__getitem__(header)

返回给定标头名称的值。不区分大小写。

HttpResponse.get(header, alternate=None)

返回给定标头或 alternate 的值,如果标头不存在。

HttpResponse.has_header(header)

基于给定名称的标头(不区分大小写)检查,返回 TrueFalse

HttpResponse.items()

对响应上的 HTTP 标头执行 dict.items() 的操作。

HttpResponse.setdefault(header, value)

设置标头,除非它已被设置。

设置 cookie。参数与 Python 标准库中的 Morsel cookie 对象中的参数相同。

  • max_age 应为 timedelta 对象、一个整数秒数或 None(默认值),如果 cookie 应仅持续到客户端的浏览器会话。如果未指定 expires,则将计算它。

  • expires 应为格式为 "Wdy, DD-Mon-YY HH:MM:SS GMT" 的字符串或 UTC 中的 datetime.datetime 对象。如果 expiresdatetime 对象,则将计算 max_age

  • 如果您想设置跨域 cookie,请使用 domain。例如,domain="example.com" 将设置一个可由 www.example.com、blog.example.com 等域读取的 cookie。否则,cookie 将只能由设置它的域读取。

  • 如果您希望仅在使用 https 方案发出请求时才将 cookie 发送到服务器,请使用 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 字节的 cookie。对于许多浏览器来说,这也是最大大小。如果尝试存储超过 4096 字节的 cookie,Django 不会引发异常,但许多浏览器不会正确设置 cookie。

set_cookie() 类似,但在设置 cookie 之前,对 cookie 进行 加密签名。结合 HttpRequest.get_signed_cookie() 使用。你可以使用可选的 salt 参数来增强密钥强度,但你需要记住将其传递给相应的 HttpRequest.get_signed_cookie() 调用。

删除具有给定键的 cookie。如果键不存在,则静默失败。

由于 cookie 的工作方式,pathdomain 应该是你在 set_cookie() 中使用的相同值,否则 cookie 可能无法被删除。

HttpResponse.close()

此方法在请求结束时由 WSGI 服务器直接调用。

HttpResponse.write(content)

此方法使 HttpResponse 实例成为类似文件的对象。

HttpResponse.flush()

此方法使 HttpResponse 实例成为类似文件的对象。

HttpResponse.tell()

此方法使 HttpResponse 实例成为类似文件的对象。

HttpResponse.getvalue()

返回 HttpResponse.content 的值。此方法使 HttpResponse 实例成为类似流的对象。

HttpResponse.readable()

始终 False。此方法使 HttpResponse 实例成为类似流的对象。

HttpResponse.seekable()

始终 False。此方法使 HttpResponse 实例成为类似流的对象。

HttpResponse.writable()

始终 True。此方法使 HttpResponse 实例成为类似流的对象。

HttpResponse.writelines(lines)

将行列表写入响应。不添加行分隔符。此方法使 HttpResponse 实例成为类似流的对象。

HttpResponse 子类

Django 包含许多处理不同类型 HTTP 响应的 HttpResponse 子类。与 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),而不是“已找到”重定向(状态代码 302)。

HttpResponseNotModified

构造函数不接受任何参数,且不应向此响应添加内容。使用此来指定页面自用户上次请求后未修改(状态代码 304)。

HttpResponseBadRequest

行为就像 HttpResponse,但使用 400 状态代码。

HttpResponseNotFound

行为就像 HttpResponse,但使用 404 状态代码。

HttpResponseForbidden

行为就像 HttpResponse,但使用 403 状态代码。

HttpResponseNotAllowed

类似 HttpResponse,但使用 405 状态代码。构造函数的第一个参数是必需的:允许的方法列表(例如 ['GET', 'POST'])。

HttpResponseGone

作用类似于 HttpResponse,但使用 410 状态代码。

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 对象

JsonResponse(data, encoder=DjangoJSONEncoder, safe=True, json_dumps_params=None, **kwargs)

一个 HttpResponse 子类,用于创建 JSON 编码的响应。它继承了其超类的多数行为,但有一些不同之处

其默认的 Content-Type 标头设置为 application/json

第一个参数 data 应为 dict 实例。如果 safe 参数设置为 False(见下文),它可以是任何可 JSON 序列化的对象。

默认情况下为 django.core.serializers.json.DjangoJSONEncoderencoder 将用于序列化数据。有关此序列化器的更多详细信息,请参阅 JSON 序列化

布尔参数 safe 的默认值为 True。如果将其设置为 False,则可以传递任何对象进行序列化(否则,仅允许 dict 实例)。如果 safeTrue,并且将非 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 编码的响应中使用非 dict 对象。

警告

ECMAScript 的第 5 版 之前,可以破坏 JavaScript Array 构造函数。出于此原因,Django 默认情况下不允许将非 dict 对象传递给 JsonResponse 构造函数。但是,大多数现代浏览器都实现了 ECMAScript 5,它消除了此攻击媒介。因此,可以禁用此安全预防措施。

更改默认 JSON 编码器

如果需要使用不同的 JSON 编码器类,可以将 encoder 参数传递给构造函数方法

>>> response = JsonResponse(data, encoder=MyJSONEncoder)

StreamingHttpResponse 对象

class StreamingHttpResponse

StreamingHttpResponse 类用于将响应从 Django 流式传输到浏览器。

高级用法

StreamingHttpResponse 有点高级,因为了解在 WSGI 下同步提供应用程序还是在 ASGI 下异步提供应用程序并相应地调整使用方式非常重要。

请仔细阅读这些说明。

在 WSGI 下使用 StreamingHttpResponse 的一个示例用法是在生成响应时流式传输内容会花费太长时间或使用太多内存。例如,它对于 生成大型 CSV 文件 很有用。

不过,在执行此操作时需要考虑性能。在 WSGI 下,Django 被设计为处理短时请求。流式传输响应会将工作进程绑定在整个响应期间。这可能会导致性能不佳。

一般来说,您会在请求-响应周期之外执行昂贵的任务,而不是诉诸流式传输响应。

但是,在 ASGI 下提供服务时,StreamingHttpResponse 不必阻止其他请求在等待 I/O 时得到响应。这为流式传输内容的长时请求以及实现诸如长轮询和服务器发送事件之类的模式开辟了可能性。

即使在 ASGI 下注意,StreamingHttpResponse 也只应在绝对需要在将数据传输到客户端之前不迭代整个内容的情况下使用。因为无法访问内容,许多中间件无法正常运行。例如,无法为流式传输响应生成 ETagContent-Length 标头。

StreamingHttpResponse 不是 HttpResponse 的子类,因为它具有略有不同的 API。但是,它几乎是相同的,具有以下显着差异

  • 它应该给出一个生成字节串、memoryview 或字符串的内容的迭代器。在 WSGI 下提供服务时,这应该是一个同步迭代器。在 ASGI 下提供服务时,它应该是一个异步迭代器。

  • 您无法访问其内容,除非迭代响应对象本身。这应该只在将响应返回给客户端时发生:您不应该自己迭代响应。

    在 WSGI 下,响应将同步迭代。在 ASGI 下,响应将异步迭代。(这就是迭代器类型必须与您使用的协议匹配的原因。)

    为了避免崩溃,在迭代过程中,不正确的迭代器类型将被映射到正确的类型,并且会引发警告,但为了执行此操作,必须完全消耗迭代器,这违背了使用 StreamingHttpResponse 的目的。

  • 它没有 content 属性。相反,它有一个 streaming_content 属性。这可以在中间件中用于包装响应可迭代对象,但不能消耗。

  • 您不能使用类似文件的对象 tell()write() 方法。这样做会引发异常。

HttpResponseBase 基类在 HttpResponseStreamingHttpResponse 之间是通用的。

在 Django 4.2 中更改

添加了对异步迭代的支持。

属性

StreamingHttpResponse.streaming_content

响应内容的迭代器,字节串根据 HttpResponse.charset 编码。

StreamingHttpResponse.status_code

HTTP 状态代码 响应。

除非 reason_phrase 被明确设置,修改构造函数外部的 status_code 的值也会修改 reason_phrase 的值。

StreamingHttpResponse.reason_phrase

响应的 HTTP 原因短语。它使用 HTTP 标准 的默认原因短语。

除非明确设置,否则 reason_phrasestatus_code 的值决定。

StreamingHttpResponse.streaming

这始终为 True

StreamingHttpResponse.is_async
Django 4.2 中的新增功能。

指示 StreamingHttpResponse.streaming_content 是异步迭代器还是不是的布尔值。

这对于需要包装 StreamingHttpResponse.streaming_content 的中间件很有用。

处理断开连接

Django 5.0 中的新增功能。

如果客户端在流式响应期间断开连接,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 对象

FileResponse(open_file, as_attachment=False, filename='', **kwargs)

FileResponseStreamingHttpResponse的子类,针对二进制文件进行了优化。如果 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标头会自动设置。

当可以从filenameopen_file的名称中猜测时,Content-Type标头会自动设置。

FileResponse接受任何具有二进制内容的文件类对象,例如以二进制模式打开的文件,如下所示

>>> from django.http import FileResponse
>>> response = FileResponse(open("myfile.png", "rb"))

文件将自动关闭,因此不要使用上下文管理器打开它。

在 ASGI 下使用

Python 的文件 API 是同步的。这意味着必须完全消费文件才能在 ASGI 下提供服务。

要异步流式传输文件,你需要使用提供异步文件 API 的第三方包,例如 aiofiles

方法

FileResponse.set_headers(open_file)

此方法在响应初始化期间自动调用,并根据 open_file 设置各种标头(Content-LengthContent-TypeContent-Disposition)。

HttpResponseBase

class HttpResponseBase

HttpResponseBase 类适用于所有 Django 响应。不应将其用于直接创建响应,但它可用于类型检查。

返回顶部