Django REST framework--API手册: Renderers

REST framework 包括许多内置的 Renderer 类,允许您返回具有各种媒体类型的响应。还支持定义您自己的自定义渲染器,这使您可以灵活地设计自己的媒体类型。

怎样确定渲染器

视图的一组始终定义为类列表的有效渲染器。当进入视图时,REST framework 将对传入的请求执行内容协商,并确定最合适的渲染器来满足请求。

内容协商的基本过程包括检查请求的 Accept 标头,以确定它在响应中期望的媒体类型。可选地,URL 上的格式后缀可用于显式请求特定表示。例如 URL http://example.com/api/users_count.json 应当是终端总是返回 JSON 数据.

更多信息请看内容协商 ( content negotiation .)

渲染器设置

可以使用 DEFAULT_RENDERER_CLASSES 设置全局设置默认的渲染器集合。例如,以下设置将使用 JSON 作为主要媒体类型,而且叶包括自描述 API。

REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
}

您还可以使用基于 APIView 视图类的视图设置用于单个视图或视图集的渲染器。

from django.contrib.auth.models import User
from rest_framework.renderers import JSONRenderer
from rest_framework.response import Response
from rest_framework.views import APIView
class UserCountView(APIView):
    A view that returns the count of active users in JSON.
    renderer_classes = [JSONRenderer]
    def get(self, request, format=None):
        user_count = User.objects.filter(active=True).count()
        content = {'user_count': user_count}
        return Response(content)

或者, 如果你使用 @api_view 修饰符和基于函数的视图可以这样一起使用 .

@api_view(['GET'])
@renderer_classes([JSONRenderer])
def user_count_view(request, format=None):
    A view that returns the count of active users in JSON.
    user_count = User.objects.filter(active=True).count()
    content = {'user_count': user_count}
    return Response(content)

渲染器 的顺序

在为 API 指定渲染器类时,考虑要为每种媒体类型分配的优先级非常重要。如果客户端未指定它可以接受的表示,例如发送 Accept: */* 标头,或者根本不包含 Accept 标头,则 REST framework 将选择列表中的第一个渲染器用于响应。

例如,如果您的 API 服务器提供 JSON 响应和 HTML 可浏览 API,您可能希望将 JSONRenderer 设为默认渲染器,以便将 JSON 响应发送到未指定 Accept 标头的客户端。

如果您的 API 包含可以根据请求提供常规网页和 API 响应的视图,那么您可以考虑将 TemplateHTMLRenderer 设为默认渲染器,以便与发送损坏的接受标头的旧浏览器完美配合。


API 参考

JSONRenderer

使用 utf-8 编码将请求数据呈现为 JSON。

请注意,默认样式是包含 unicode 字符,并使用没有不必要空格的紧凑样式呈现响应:

{"unicode black star":"★","value":999}

The client may additionally include an 'indent' media type parameter, in which case the returned JSON will be indented. For example Accept: application/json; indent=4 .

{
    "unicode black star": "★",
    "value": 999
}

The default JSON encoding style can be altered using the UNICODE_JSON and COMPACT_JSON settings keys.

.media_type : application/json

.format : 'json'

.charset : None

TemplateHTMLRenderer

使用 Django 的标准模板呈现将数据呈现为 HTML。与其他渲染器不同,传递给 Response 的数据不需要序列化。此外,与其他渲染器不同,您可能希望在创建响应时包含 template_name 参数。

TemplateHTMLRenderer 将创建一个 RequestContext,使用 response.data 作为上下文字典,并确定用于呈现上下文的模板名称。

注意: 当与使用序列化程序的视图一起使用时,为呈现而发送的响应可能不是字典,需要在返回之前包装在字典中以允许 TemplateHTMLRenderer 呈现它。例如:

response.data = {'results': response.data}

模板名称由的确定(按优先顺序):

  1. 一个传递给 response 的显式参数 template_name .
  2. 一个为这个类设置的显式属性 .template_name attribute set on this class.
  3. 调用 view.get_template_names() 的返回结果。

一个使用 TemplateHTMLRenderer 的例子:

class UserDetail(generics.RetrieveAPIView):
    A view that returns a templated HTML representation of a given user.
    queryset = User.objects.all()
    renderer_classes = [TemplateHTMLRenderer]
    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        return Response({'user': self.object}, template_name='user_detail.html')

您可以使用 TemplateHTMLRenderer 使用 REST 框架返回常规 HTML 页面,或者从单个端点返回 HTML 和 API 响应。

如果您正在构建使用 TemplateHTMLRenderer 和其他渲染器类的网站,您应该考虑将 TemplateHTMLRenderer 列为 renderer_classes 列表中的第一个类,这样即使对于发送格式错误的 ACCEPT: headers 的浏览器,它也会被优先考虑。

有关 TemplateHTMLRenderer 用法的更多示例,请参阅 HTML & Forms Topic Page。

.media_type : text/html

.format : 'html'

.charset : utf-8

See also: StaticHTMLRenderer

StaticHTMLRenderer

一个简单的渲染器,它只返回预渲染的 HTML。与其他渲染器不同,传递给响应对象的数据应该是表示要返回的内容的字符串。

一个使用 StaticHTMLRenderer 的例子视图:

@api_view(['GET'])
@renderer_classes([StaticHTMLRenderer])
def simple_html_view(request):
    data = '<html><body><h1>Hello, world</h1></body></html>'
    return Response(data)

您可以使用 StaticHTMLRenderer 使用 REST 框架返回常规 HTML 页面,或者从单个端点返回 HTML 和 API 响应。

.media_type : text/html

.format : 'html'

.charset : utf-8

See also: TemplateHTMLRenderer

BrowsableAPIRenderer

将数据呈现为可浏览 API 的 HTML:



此渲染器将比其他渲染器具有最高优先级,并使用该渲染器在 HTML 页面中显示 API 样式响应。

.media_type : text/html

.format : 'api'

.charset : utf-8

.template : 'rest_framework/api.html'

Customizing BrowsableAPIRenderer

默认情况下,响应内容将使用除 BrowsableAPIRenderer 之外的最高优先级渲染器进行渲染。如果您需要自定义此行为,例如使用 HTML 作为默认返回格式,但在可浏览 API 中使用 JSON,您可以通过覆盖 get_default_renderer() 方法来实现。例如::

class CustomBrowsableAPIRenderer(BrowsableAPIRenderer):
    def get_default_renderer(self, view):
        return JSONRenderer()

AdminRenderer

将数据渲染为 HTML 以进行类似管理员的显示:


此渲染器适用于 CRUD 样式的 Web API,这些 API 还应提供用于管理数据的用户友好界面。

请注意,为其输入嵌套或列表序列化程序的视图将无法与 AdminRenderer 配合使用,因为 HTML 表单无法正确支持它们。

注意 : 当数据中存在正确配置的 URL_FIELD_NAME(默认为 url)属性时,AdminRenderer 只能包含指向详细信息页面的链接。对于 HyperlinkedModelSerializer 就是这种情况,但对于 ModelSerializer 或普通 Serializer 类,您需要确保明确包含该字段。例如这里我们使用模型 get_absolute_url 方法:

class AccountSerializer(serializers.ModelSerializer):
    url = serializers.CharField(source='get_absolute_url', read_only=True)
    class Meta:
        model = Account

.media_type : text/html

.format : 'admin'

.charset : utf-8

.template : 'rest_framework/admin.html'

HTMLFormRenderer

将序列化程序返回的数据呈现为 HTML 表单。此渲染器的输出不包括封闭的 <form> 标签、隐藏的 CSRF 输入或任何提交按钮。

此渲染器不打算直接使用,而是可以通过将序列化实例传递给 render_form 模板标记来在模板中使用。

{% load rest_framework %}
<form action="/submit-report/" method="post">
    {% csrf_token %}
    {% render_form serializer %}
    <input type="submit" value="Save" />
</form>

更多信息请看 HTML & Forms 文档.

.media_type : text/html

.format : 'form'

.charset : utf-8

.template : 'rest_framework/horizontal/form.html'

MultiPartRenderer

此渲染器用于渲染 HTML 多部分表单数据。它不适合作为响应渲染器,而是用于创建测试请求,使用 REST 框架的测试客户端和测试请求工厂.

.media_type : multipart/form-data; boundary=BoUnDaRyStRiNg

.format : 'multipart'

.charset : utf-8


定制 renderers

要实现自定义渲染器,您应该覆盖 BaseRenderer,设置 .media_type 和 .format 属性,并实现 .render(self, data, media_type=None, renderer_context=None) 方法.

该方法应返回一个字节串,它将用作 HTTP 响应的主体。

传递给 .render() 方法的参数是:

data

请求数据, 由 Response() 实例设定.

media_type=None

可选项。如果提供,这是由内容协商阶段确定的可接受的媒体类型。

根据客户端的 Accept: header,这可能比渲染器的 media_type 属性更具体,并且可能包括媒体类型参数。例如“application/json; nested=true”。

renderer_context=None

可选的。如果提供,这是视图提供的上下文信息字典。

默认情况下,这将包括以下键:view、request、response、args、kwargs。

例子

下面是一个示例纯文本渲染器,它将返回一个带有 data 参数作为响应内容的响应。

from django.utils.encoding import smart_text
from rest_framework import renderers
class PlainTextRenderer(renderers.BaseRenderer):
    media_type = 'text/plain'
    format = 'txt'
    def render(self, data, media_type=None, renderer_context=None):
        return smart_text(data, encoding=self.charset)

设置字符集

默认情况下,渲染器类假定使用 UTF-8 编码。要使用不同的编码,请在渲染器上设置 charset 属性。

class PlainTextRenderer(renderers.BaseRenderer):
    media_type = 'text/plain'
    format = 'txt'
    charset = 'iso-8859-1'
    def render(self, data, media_type=None, renderer_context=None):
        return data.encode(self.charset)

请注意,如果渲染器类返回 unicode 字符串,则响应内容将被 Response 类强制转换为一个 bytestring ,渲染器上设置的 charset 属性用于确定编码。

如果渲染器返回一个表示原始二进制内容的 bytestring ,您应该将字符集值设置为 None,这将确保响应的 Content-Type 标头不会设置字符集值。

在某些情况下,您可能还想将 render_style 属性设置为“binary”。这样做还可以确保可浏览 API 不会尝试将二进制内容显示为字符串。

class JPEGRenderer(renderers.BaseRenderer):
    media_type = 'image/jpeg'
    format = 'jpg'
    charset = None
    render_style = 'binary'
    def render(self, data, media_type=None, renderer_context=None):
        return data

高级渲染器使用

您可以使用 REST 框架的渲染器做一些非常灵活的事情。一些例子...

  • 根据请求的媒体类型,提供来自同一端点的平面或嵌套表示。
  • 指定多种类型的 HTML 表示供 API 客户端使用.
  • 未指定渲染器的媒体类型,例如使用 media_type = 'image/*',并使用 Accept header来改变响应的编码。

不同媒体类型的行为

在某些情况下,您可能希望视图根据接受的媒体类型使用不同的序列化样式。如果您需要这样做,您可以访问 request.accepted_renderer 以确定将用于响应的协商渲染器。

例如:

@api_view(['GET'])
@renderer_classes([TemplateHTMLRenderer, JSONRenderer])
def list_users(request):
    A view that can return JSON or HTML representations
    of the users in the system.
    queryset = Users.objects.filter(active=True)
    if request.accepted_renderer.format == 'html':
        # TemplateHTMLRenderer takes a context dict,
        # and additionally requires a 'template_name'.
        # It does not require serialization.
        data = {'users': queryset}
        return Response(data, template_name='list_users.html')
    # JSONRenderer requires serialized data as normal.
    serializer = UserSerializer(instance=queryset)
    data = serializer.data
    return Response(data)

未指定 media 类型

在某些情况下,您可能希望渲染器提供一个系列媒体类型。在这种情况下,您可以通过使用诸如 image/* 或 */* 之类的 media_type 值来指定它应该响应的媒体类型。

如果您未指定渲染器的媒体类型,则应确保在返回响应时使用 content_type 属性明确指定媒体类型。例如:

return Response(data, content_type='image/png')

设计你的 media 类型

对于许多 Web API 而言,具有超链接关系的简单 JSON 响应可能就足够了。如果您想完全接受 RESTful 设计和 HATEOAS,您需要更详细地考虑media类型的设计和使用。

用 Roy Fielding 的话来说,“REST API 应该花费几乎所有的描述性工作来定义用于表示资源和驱动应用程序状态的媒体类型,或者定义扩展关系名称和/或启用超文本的标记——适用于现有的标准媒体类型。”。

有关自定义媒体类型的良好示例,请参阅 GitHub 使用自定义 application /vnd.github+json 媒体类型和 Mike Amundsen 的 IANA 批准的 application /vnd.collection+json 基于 JSON 的超媒体。

HTML error views

通常,渲染器的行为是相同的,无论它是处理常规响应,还是处理由引发的异常(例如 Http404 或 PermissionDenied 异常,或 APIException 的子类)引起的响应。

如果您使用 TemplateHTMLRenderer 或 StaticHTMLRenderer 并引发异常,则行为略有不同,并且反映了 Django 对错误视图的默认处理。

由 HTML 渲染器引发和处理的异常将尝试按优先顺序使用以下方法之一进行渲染。

  • 加载并呈现名为 {status_code}.html 的模板.
  • 加载并呈现名为 api_exception.html 的模板.
  • 呈现 HTTP 状态代码和文本, 例如 "404 Not Found".

模板将使用包含 status_code 和 details 键的 RequestContext 呈现。

注意: 如果 DEBUG=True,将显示 Django 的标准回溯错误页面,而不是呈现 HTTP 状态代码和文本。


第三方包

下面的第三方包也可以利用.

YAML

REST framework YAML 提供 YAML 解析和渲染支持。它以前直接包含在 REST 框架包中,现在作为第三方包被支持。

安装和配置

安装使用 pip.

$ pip install djangorestframework-yaml

修改你的 REST framework 设置.

REST_FRAMEWORK = {
    'DEFAULT_PARSER_CLASSES': [
        'rest_framework_yaml.parsers.YAMLParser',
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework_yaml.renderers.YAMLRenderer',
}

XML

REST Framework XML 提供了一种简单的非正式 XML 格式。它以前直接包含在 REST 框架包中,现在作为第三方包被支持。

安装和配置

安装使用 pip.

$ pip install djangorestframework-xml

修改你的 REST framework 设置.

REST_FRAMEWORK = {
    'DEFAULT_PARSER_CLASSES': [
        'rest_framework_xml.parsers.XMLParser',
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework_xml.renderers.XMLRenderer',
}

JSONP

REST framework JSONP 提供 JSONP 渲染支持。它以前直接包含在 REST 框架包中,现在作为第三方包被支持。

警告 : 如果您需要跨域 AJAX 请求,您通常应该使用更现代的 CORS 方法作为 JSONP 的替代方法。有关更多详细信息,请参阅 CORS 文档。

jsonp 方法本质上是一种浏览器 hack,仅适用于全局可读的 API 端点,其中 GET 请求未经身份验证且不需要任何用户权限。

安装和配置

安装使用 pip.

$ pip install djangorestframework-jsonp

修改你的 REST framework 设置.

REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework_jsonp.renderers.JSONPRenderer',
}

MessagePack

MessagePack 是一种快速、高效的二进制序列化格式。 Juan Riaza 维护 djangorestframework-msgpack 包,该包为 REST 框架提供 MessagePack 渲染器和解析器支持。

XLSX ( 二进制电子表格端点 Binary Spreadsheet Endpoints)

XLSX 是世界上最流行的二进制电子表格格式。沃顿商学院的蒂姆艾伦维护 drf-renderer-xlsx,它使用 OpenPyXL 将端点呈现为 XLSX 电子表格,并允许客户端下载它。电子表格可以基于每个视图进行样式设置。

安装和配置

安装使用 pip.

$ pip install drf-renderer-xlsx

修改你的 REST framework 设置.

REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
        'drf_renderer_xlsx.renderers.XLSXRenderer',
}

为了避免在没有文件名的情况下流式传输文件(浏览器通常默认为文件名“下载”,没有扩展名),我们需要使用 mixin 来覆盖 Content-Disposition 标头。如果未提供文件名,则默认为 export.xlsx。例如:

from rest_framework.viewsets import ReadOnlyModelViewSet
from drf_renderer_xlsx.mixins import XLSXFileMixin
from drf_renderer_xlsx.renderers import XLSXRenderer
from .models import MyExampleModel
from .serializers import MyExampleSerializer