# Django 3.2.11.dev 文档

# `TemplateResponse` 和 `SimpleTemplateResponse`

标准 `HttpResponse` 对象是静态结构。它们在构建时提供了一个预渲染的内容块，虽然这些内容可以修改，但它的形式并不便于进行修改。

然而，有时允许装饰者或中间件在视图构建响应后修改响应可能是有益的。例如，你可能想改变所使用的模板，或者在上下文中放入额外的数据。

TemplateResponse 提供了一种方法来实现这一点。与基本的 `HttpResponse` 对象不同，TemplateResponse 对象保留了模板和上下文的细节，这些细节是由视图提供的，用于计算响应。响应的最终输出直到需要时才会计算，在响应过程的后面。

## `SimpleTemplateResponse` 对象

class `SimpleTemplateResponse`

### 属性

`SimpleTemplateResponse.``template_name`

  要渲染的模板的名称。接受一个依赖于后台的模板对象（如 `get_template()` 返回的模板对象）、一个模板的名称或一个模板名称列表。

  例如： `['foo.html', 'path/to/bar.html']`

`SimpleTemplateResponse.``context_data`

  渲染模板时要使用的上下文数据，必须是 `dict`。

  例如： `{'foo': 123}`

`SimpleTemplateResponse.``rendered_content`

  响应内容的当前渲染值，使用当前模板和上下文数据。

`SimpleTemplateResponse.``is_rendered`

  表示响应内容是否已呈现的布尔值。

### 方法

`SimpleTemplateResponse.``__init__`(template, context=None, content_type=None, status=None, charset=None, using=None, headers=None)

  用给定的模板、上下文、内容类型、HTTP 状态和字符集实例化一个 `SimpleTemplateResponse` 对象。

  `template`
    依赖于后台的模板对象（如 `get_template()` 返回的模板对象），模板的名称，或者模板名称的列表。
  `context`
    一个 `dict` 的值，用于添加到模板上下文中。默认情况下，这是一个空字典。
  `content_type`
    包含在 HTTP `Content-Type` 头中的值，包括 MIME 类型规格和字符集编码。如果指定了 `content_type`，则使用其值。否则，使用 `'text/html'`。
  `status`
    响应的 HTTP 状态码。
  `charset`
    响应将被编码的字符集。如果没有给定，将从 `content_type` 中提取，如果不成功，将使用 `DEFAULT_CHARSET` 设置。
  `using`
    用于加载模板的模板引擎的 `NAME` 。
  `headers`
    A `dict` of HTTP headers to add to the response.
  Changed in Django 3.2:

  The `headers` parameter was added.

`SimpleTemplateResponse.``resolve_context`(context)

  预处理将用于渲染模板的上下文数据。接受一个 `dict` 的上下文数据。默认情况下，返回相同的 `dict`。

  覆盖此方法，以自定义上下文。

`SimpleTemplateResponse.``resolve_template`(template)

  解析用于渲染的模板实例。接受一个依赖于后台的模板对象（例如 `get_template()` 返回的对象），模板的名称，或者模板名称的列表。

  返回要渲染的依赖于后台的模板对象实例。

  覆盖此方法，以便自定义模板加载。

`SimpleTemplateResponse.``add_post_render_callback`()

  添加一个回调，将在渲染发生后被调用。该钩子可用于将某些处理操作（如缓存）推迟到渲染发生后。

  如果 `SimpleTemplateResponse` 已经被渲染，回调将被立即调用。

  当调用时，回调将被传递一个单一的参数——渲染的 `SimpleTemplateResponse` 实例。

  如果回调返回一个不是 `None` 的值，这个值将被用作响应，而不是原来的响应对象（并将传递给下一个渲染后回调等）。

`SimpleTemplateResponse.``render`()

  将 `response.content` 设置为由 `SimpleTemplateResponse.rendered_content` 得到的结果，运行所有的渲染后回调，并返回结果的响应对象。

  `render()` 只有在第一次被调用时才会产生效果。在以后的调用中，它将返回第一次调用的结果。

## `TemplateResponse` 对象

class `TemplateResponse`

  `TemplateResponse` 是 `SimpleTemplateResponse` 的一个子类，它知道当前的 `HttpRequest`。

### 方法

`TemplateResponse.``__init__`(request, template, context=None, content_type=None, status=None, charset=None, using=None, headers=None)

  用给定的请求、模板、上下文、内容类型、HTTP 状态和字符集实例化一个 `TemplateResponse` 对象。

  `request`
    一个 `HttpRequest` 实例。
  `template`
    依赖于后台的模板对象（如 `get_template()` 返回的模板对象），模板的名称，或者模板名称的列表。
  `context`
    一个 `dict` 的值，用于添加到模板上下文中。默认情况下，这是一个空字典。
  `content_type`
    包含在 HTTP `Content-Type` 头中的值，包括 MIME 类型规格和字符集编码。如果指定了 `content_type`，则使用其值。否则，使用 `'text/html'`。
  `status`
    响应的 HTTP 状态码。
  `charset`
    响应将被编码的字符集。如果没有给定，将从 `content_type` 中提取，如果不成功，将使用 `DEFAULT_CHARSET` 设置。
  `using`
    用于加载模板的模板引擎的 `NAME` 。
  `headers`
    A `dict` of HTTP headers to add to the response.
  Changed in Django 3.2:

  The `headers` parameter was added.

## 渲染过程

在将 `TemplateResponse` 实例返回给客户端之前，必须对其进行渲染。渲染过程将模板和上下文的中间表示方式，变成最终的字节流，可以提供给客户端。

在三种情况下，会出现 `TemplateResponse` 被渲染：

- 当使用 `SimpleTemplateResponse.render()` 方法显式渲染 `TemplateResponse` 实例时。
- 当通过指定 `response.content` 明确设置响应的内容时。
- 通过模板响应中间件后，但在通过响应中间件之前。

一个 `TemplateResponse` 只能被渲染一次。第一次调用 `SimpleTemplateResponse.render()` 时，会设置响应的内容；后续的渲染调用不会改变响应内容。

但是，当 `response.content` 被显式分配时，变化总是被应用。如果你想强制重新渲染内容，你可以重新执行渲染的内容，并手动分配响应的内容：

    # Set up a rendered TemplateResponse
    >>> from django.template.response import TemplateResponse
    >>> t = TemplateResponse(request, 'original.html', {})
    >>> t.render()
    >>> print(t.content)
    Original content

    # Re-rendering doesn't change content
    >>> t.template_name = 'new.html'
    >>> t.render()
    >>> print(t.content)
    Original content

    # Assigning content does change, no render() call required
    >>> t.content = t.rendered_content
    >>> print(t.content)
    New content

### 渲染后回调

有些操作——例如缓存——不能在未渲染的模板上执行。它们必须在一个完全完整的、已渲染的响应上执行。

如果你使用的是中间件，你可以这样做。中间件提供了多种机会来处理从视图退出时的响应。如果你把行为放在响应中间件中，就会保证在模板渲染发生后执行。

然而，如果你使用的是一个装饰器，则不存在同样的机会。任何在装饰器中定义的行为都会被立即处理。

为了弥补这一点（以及任何其他类似的用例）， `TemplateResponse` 允许你注册回调，当渲染完成后，这些回调将被调用。使用这个回调，你可以将关键的处理推迟到可以保证渲染内容可用的时候。

要定义一个渲染后的回调，定义一个接受一个参数 response 的函数，然后用模板响应注册该函数：

    from django.template.response import TemplateResponse

    def my_render_callback(response):
        # Do content-sensitive processing
        do_post_processing()

    def my_view(request):
        # Create a response
        response = TemplateResponse(request, 'mytemplate.html', {})
        # Register the callback
        response.add_post_render_callback(my_render_callback)
        # Return the response
        return response

`my_render_callback()` 将在 `mytemplate.html` 被渲染后被调用，并将提供完全渲染的 `TemplateResponse` 实例作为参数。

如果模板已经被渲染，回调将被立即调用。

## 使用 `TemplateResponse` 和 `SimpleTemplateResponse`

一个 `TemplateResponse` 对象可以被用于任何可以使用普通 `django.http.HttpResponse` 的地方。它也可以作为调用 `render()` 的替代。

例如，下面的视图返回一个 `TemplateResponse`，其中有一个模板和一个包含查询集的上下文：

    from django.template.response import TemplateResponse

    def blog_index(request):
        return TemplateResponse(request, 'entry_list.html', {'entries': Entry.objects.all()})