# Django 3.2.11.dev 文档

# 请求和响应对象

## 快速概述

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

当一个页面被请求时，Django 会创建一个 `HttpRequest` 对象，这个对象包含了请求的元数据。然后，Django 加载相应的视图，将 `HttpRequest` 作为视图函数的第一个参数。每个视图负责返回一个 `HttpResponse` 对象。

本文档解释了 `django.http` 模块中定义的 `HttpRequest` 和 `HttpResponse` 对象的 API。

## `HttpRequest` 对象

class `HttpRequest`

### 属性

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

`HttpRequest.``scheme`

  代表请求协议的字符串（通常是 `http` 或 `https`）。

`HttpRequest.``body`

  原始的 HTTP 请求体作为一个字节字符串。这对于以不同方式处理非常规 HTML 表单的数据很有用：二进制图像，XML 有效负载等。对于处理传统的表单数据，使用 `HttpRequest.POST`。

  你也可以使用类似文件的接口 `HttpRequest.read()` 或 `HttpRequest.readline()` 从 `HttpRequest` 中读取。在使用这些 I/O 流方法中的任何一种方法读取请求后，访问 `body` 属性会产生 `RawPostDataException`。

`HttpRequest.``path`

  A string representing the full path to the requested page, not including the scheme, domain, or query string.

  例如：`"/music/bands/the_beatles/"`

`HttpRequest.``path_info`

  在某些 Web 服务器的配置下，主机名之后的 URL 部分被分割成脚本前缀部分和路径信息部分。`path_info` 属性总是包含路径的路径信息部分，无论使用的是什么 Web 服务器。使用它代替 `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.``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`

  一个包含所有 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.``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`

  来自 `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.

### 方法

`HttpRequest.``get_host`()

  使用 `HTTP_X_FORWARDED_HOST` （如果 `USE_X_FORWARDED_HOST` 已启用）和 `HTTP_HOST` 头信息，按顺序返回请求的发起主机。如果它们没有提供一个值，则该方法使用 `SERVER_NAME` 和 `SERVER_PORT` 的组合，详见 PEP 3333。

  例如：`"127.0.0.1:8000"`

  Raises `django.core.exceptions.DisallowedHost` if the host is not in `ALLOWED_HOSTS` or the domain name is invalid according to RFC 1034/1035.

  注解

  `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.``is_secure`()

  如果请求是安全的，返回 `True`；如果请求是通过 HTTPS 发出的，返回 `True`。

`HttpRequest.``accepts`(mime_type)
  New in Django 3.1.

  如果请求的 `Accept` 头符合 `mime_type` 参数，则返回 `True`。

      >>> request.accepts('text/html')
      True

  大多数浏览器默认发送 `Accept: */*`，默认情况下，这将为所有内容类型返回 `True`。在 API 请求中设置一个显式的 `Accept` 头，对于只为那些消费者返回不同的内容类型是很有用的。参见 内容协商示例 使用 `accepts()` 向 API 消费者返回不同的内容。

  如果一个响应根据 `Accept` 头的内容而变化，并且你使用了某种形式的缓存，比如 Django 的 `cache middleware`，你应该用 `vary_on_headers('Accept')` 来装饰视图，这样响应就会被正确地缓存。

`HttpRequest.``is_ajax`()

  3.1 版后已移除.

  如果请求是通过 `XMLHttpRequest` 发出的，则返回 `True`，检查 `HTTP_X_REQUESTED_WITH` 头中是否有 `'XMLHttpRequest'`。大多数现代 JavaScript 库都会发送这个头。如果你写了自己的 `XMLHttpRequest` 调用（在浏览器端），如果你想让 `is_ajax()` 工作，你必须手动设置这个头。

  如果一个响应因是否通过 AJAX 请求而变化，并且你使用了某种形式的缓存，比如 Django 的 `cache middleware`，你应该用 `vary_on_headers('X-Requested-With')` 来装饰视图，这样响应就会被正确缓存。

`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` 对象中， `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)

  创建一个新的 `QueryDict`，键来自 `iterable`，每个值等于 `value`。例如：

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

  返回 `QueryDict` 的 `dict` 表示。对于 `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` 类来代替。

#### 设置头字段

To set or remove a header field in your response, use `HttpResponse.headers`:

    >>> response = HttpResponse()
    >>> response.headers['Age'] = 120
    >>> del response.headers['Age']

You can also manipulate headers by treating your response like a dictionary:

    >>> response = HttpResponse()
    >>> response['Age'] = 120
    >>> del response['Age']

This proxies to `HttpResponse.headers`, and is the original interface offered by `HttpResponse`.

When using this interface, unlike a dictionary, `del` doesn't raise `KeyError` if the header field doesn't exist.

You can also set headers on instantiation:

    >>> 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`。

Changed in Django 3.2:

The `HttpResponse.headers` interface was added.

The ability to set headers on instantiation was added.

#### 告诉浏览器将响应作为文件附件处理

To tell the browser to treat the response as a file attachment, set the `Content-Type` and `Content-Disposition` headers. For example, this is how you might return a Microsoft Excel spreadsheet:

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

`Content-Disposition` 头并没有什么 Django 特有的内容，但是很容易忘记语法，所以我们把它包含在这里。

### 属性

`HttpResponse.``content`

  一个代表内容的字节字符串，必要时由字符串编码。

`HttpResponse.``headers`
  New in Django 3.2.

  A case insensitive, dict-like object that provides an interface to all HTTP headers on the response. See 设置头字段.

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

  Instantiates an `HttpResponse` object with the given page content, content type, and headers.

  `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` is a `dict` of HTTP headers for the response.

  Changed in Django 3.2:

  The `headers` parameter was added.

`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` should be an integer number of seconds, or `None` (default) if the cookie should last only as long as the client's browser session. If `expires` is not specified, it will be calculated.

  - `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 会随着所有的同站和跨站请求而发送。

  Changed in Django 3.1:

  允许使用 `samesite='None` （字符串）。

  警告

  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()` 调用。

  Changed in Django 3.1:

  允许使用 `samesite='None` （字符串）。

`HttpResponse.``delete_cookie`(key, path='/', domain=None, samesite=None)

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

  由于 cookie 的工作方式，`path` 和 `domain` 应该与你在 `set_cookie()` 中使用的值相同，否则 cookie 可能不会被删除。

  Changed in Django 2.2.15:

  增加了 `samesite` 参数。

`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 `HttpResponseNotModified`

  构造函数不接受任何参数，也不应该添加任何内容到这个响应中。用它来表示自用户最后一次请求后，页面没有被修改（状态码 304）。

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`。

警告

Before the 5th edition of ECMAScript it was possible to poison the JavaScript `Array` constructor. For this reason, Django does not allow passing non-dict objects to the `JsonResponse` constructor by default. However, most modern browsers implement EcmaScript 5 which removes this attack vector. Therefore it is possible to disable this security precaution.

#### 更改默认 JSON 编码器

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

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

## `StreamingHttpResponse` 对象

class `StreamingHttpResponse`

`StreamingHttpResponse` 类用于从 Django 流式传输一个响应给浏览器。如果生成响应的时间太长或者使用了太多的内存，你可能需要这样做。例如，它对于 生成大型 CSV 文件 很有用。

性能考量

Django 是为短时请求设计的。流式响应会在整个响应期间绑定一个工作进程。这可能导致性能不佳。

一般来说，你应该在请求响应周期之外执行昂贵的任务，而不是求助于流式响应。

`StreamingHttpResponse` 不是 `HttpResponse` 的子类，因此它的 API 略有不同。然而，它几乎是相同的，但有以下显著的区别。

- 应该给它一个迭代器，产生字节字符串作为内容。
- 你不能访问它的内容，除非通过迭代响应对象本身。这只应该发生在响应返回给客户端的时候。
- 它没有 `content` 属性。相反，它有一个 `streaming_content` 属性。
- 你不能使用类文件对象的 `tell()` 或 `write()` 方法。这样做会引起一个异常。

`StreamingHttpResponse` 只应该用在绝对需要在将数据传输给客户端之前不对整个内容进行迭代的情况下。因为无法访问内容，所以很多中间件无法正常工作。例如 `ETag` 和 `Content-Length` 头不能为流式响应生成。

### 属性

`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`。

## `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()``。

  `Content-Length` 和 `Content-Type` 头信息是根据 `open_file` 的内容猜测出来的。

`FileResponse` 接受任何具有二进制内容的文件类对象，例如一个以二进制模式打开的文件，如：

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

该文件会自动关闭，所以不要用上下文管理器打开它。

### 方法

`FileResponse.``set_headers`(open_file)

  该方法在响应初始化过程中自动调用，并根据 `open_file` 设置各种头文件（`Content-Length`、`Content-Type` 和 `Content-Disposition`）。