REST framework包含许多内置的渲染器类,允许返回各种媒体类型的相应。还支持自定义渲染器,可以灵活地设计自己的媒体类型。

如果确定渲染器

实体的有效渲染器集集合始终被定义为类列表。进入视图时,REST框架将对传入请求执行内容协商,并确定最合适的渲染器以满足请求。
内容协商的基本过程涉及检查请求的Accept标头,以确定它在响应中期望的媒体类型。可选地,URL上的格式后缀可以用于显式地请求特定的表示。例如,http://example.com/api/users_count.json可能是始终返回JSON数据的端点。

设置渲染器

可以使用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_framewirk.views import APIView

class UserCountView(APIView):
    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)
    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成为默认的渲染器,以便向不指定Accept标头的客户端发送JSON响应。
如果API包含可以根据请求同事提供常规页面和API响应视图,那么可以考虑将TemplateHTMLRenderer设置为默认浏览器,以便与发送损坏的accept标头的旧浏览器很好地配合使用。

API参考

JSONRenderer

使用utf-8编码将请求数据渲染为JSON。
请注意,默认风格包含unicode字符,并使用紧凑风格渲染响应,没有不必要的空格:
{"unicode black star":"★","value":999}
客户端可能另外包括'indent'媒体类型参数,在这种情况下,返回JSON缩进。例如Accept: application/json; indent=4

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

使用UNICODE_JSON和COMPACT_JSON设置键可以更改默认的JSON编码样式。
.media_typeapplication/json
.format'.json'
.charsetNone

TemplateHTMLRenderer

使用Django的标准模板渲染将数据渲染为HTML。与其他渲染器不同,传递给Response的数据不需要序列化。此外,与其他渲染器不同,你可能想要在创建Response时包含template_name参数。
TemplateHTMLRenderer将创建RequestContext,使用response.data作为上下文字典,并确定用于渲染上下文的模板名称。
模板名称按以下内容进行确定(按优先顺序):

  1. 传递给响应的显式template_name参数。
  2. 在此类上设置显式的.template_name属性。
  3. 调用view.get_template_name()的返回结果。
    使用TemplateHTMLRenderer的视图示例:

    calss UserDetail(generics.RetrieveAPIView):
     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")
    

    可以使用TestPielHTMLRenderer来使用REST framework返回常规HTML页面,或者从单个端点返回HTML和API相应。
    如果正在构建使用TemplateHTMLRenderer以及其他渲染器类的网站,应该考虑将TemplateHTMLRenderer列为renderer_classes列表中的第一个类,因此对于发送格式不正确的ACCEPT标头,它甚至会优先考虑浏览器。
    .media_typetext/html
    .format'.html'
    .charsetutf-8

StaticHTMLRenderer

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

@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 framework返回常规HTML页面,或者从单个端点返回HTML和API响应。
.media_typetext/html
.format'.html'
.charsetutf-8

BrowsableAPIRenderer

为可浏览的API将数据渲染为HTML。
此渲染器将确定哪个其他渲染器将被赋予最高优先级,并使用它来显示HTML页面中API样式的响应。
.media_typetext/html
.format'.api'
.charsetutf-8
.template'rest_framework/api.html'
自定义BrowsableAPIRenderer:
默认情况下,响应内容将使用除BrosableAPIRenderer之外的最高优先级渲染器进行渲染,如果需要自定义此行为,例如使用HTML作为默认返回格式,但在可浏览的API中使用JSON,则可以通过重写get_default_renderer()方法来实现。

class CustomBroswableAPIRenderer(BroswableAPIRenderer):
    def get_default_renderer(self, view):
        return JSONRenderer()

AdminRenderer

将数据渲染为HTML以进行管理的显示。
此渲染器适用于CRUD样式的Web API,它还应提供用户友好的界面来管理数据。
注意,对于其输入具有嵌套或列表序列化程序的视图将无法与AdminRenderer一起使用,因为HTML表单无法正确支持它们。
注意:当在数据中存在正确配置的URL_FIELD_NAME(默认为url)属性时,AdminRenderer才能包含只想详细信息页面的连接。对于HyperlinkedModelSerializer,情况就是如此,但是对于ModelSerializer或者简单的Serializer类,你需要确保显式地包含该字段。
.media_typetext/html
.format'.admin'
.charsetutf-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>

.media_type: text/html
.format: '.form'
.charset: utf-8
.template: 'rest_framework/horizontal/form.html'

MultiPartRenderer

此渲染器用于渲染HTML多部分表单数据。它不适合作为响应渲染器,而是用于使用REST framework的测试客户端和测试请求工厂来创建测试请求。
.media_type: multipart/form-data; boundary=BoUnDaRyStRiNg
.format: '.multipart'
.charset: utf-8

自定义渲染器

要实现自定义渲染器,应重写BaseRenderer,设置.media_type.format属性,并且实现.render(self, data, media_type=None, renderer_context=None)方法。
该方法应当返回一个bytestring,它将被用于HTTP响应的主题。
传递给.render()方法的参数是:

  • data:
    请求数据,由Response()实例化设置。
  • media_type=None
    可选项。如果提供,这是接受的媒体类型,由内容协商阶段确定。
  • renderer_context=None
    可选项。如果提供,这是由视图提供的上下文信息的字典。

    示例:

    ```python
    from django.utils.encoding import smart_unicode
    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 data.encode(self.charset)
#### 设置字符集
默认情况下,渲染器类被假定为使用UTF-8编码,要使用其他编码,请在渲染器上设置charset属性。
```python
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类强制为bytesrting,而设置在渲染器上的字符集属性用于确定编码。
如果渲染器返回表示原始二进制内容的字节串,则应将字符集值设置为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 framework的渲染器可以做一些非常灵活的事情。示例:

  • 根据请求的媒体类型,从同一断电提供平面或嵌套表示。
  • 提供常规HTML网页和来自同一断电的基于JSON的API响应。
  • 为要使用的API客户端他指定多种类型的HTML表示。
  • 未指定渲染器的媒体类型,例如使用media_type='image/*',并使用Accept标头来更改响应的编码。

媒体类型的不同行为

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

@api_view(('GET',))
@renderer_classes((TemplateHTMLRenderer, JSONRenderer))
def list_users(request):
    queryset = Users.objects.filter(active=True)

    if request.accepted_renderer.format == 'html':
        data = {'users': queryset}
        return Response(data, template_name='list_users.html')

    serializer = UserSerializer(instance=queryset)
    data = serializer.data
    return Response(data)

未指定媒体类型

在某些情况下, 可能希望渲染器提供一些列媒体类型。在这种情况下,可以不指定应该相应的媒体类型,通过使用media_type值(诸如image/**/*)。
如果未指定渲染器的媒体类型,则应确保在使用content_type属性返回响应时显式指定媒体类型。

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

HTML错误视图

通常,无论渲染器时处理常规响应,还是处理异常引发的相应,它的行为都是一样。
由HTML渲染器引发和处理的异常将尝试按优先顺序使用一下方法之一进行渲染。

  • 加载并渲染名为{status_code}.html的模板。
  • 加载并渲染名为api_exception.html的模板。
  • 渲染HTTP状态码和文本,例如404 Not Found
    模板将用一个包含status_code和details键的RequestContext渲染。
    注意,如果DEBUG=True,Django的标准回溯错误页面将被展示,而不是渲染HTTP状态码和wenbe
0条评论

相关推荐

django教程

r

Django 2019-05-20 10:53:53

Celery

celery学习资料

Django 2019-05-25 18:41:55

django教程入门

适合django新人使用的学习手册

Django 2019-07-01 14:28:04

django实用资料

django项目从0到1自己总结的实用的资料,大部分常用的功能这里都有

Django 2019-05-08 18:21:34