在將TemplateResponse實(shí)例返回給客戶端之前,必須渲染它。渲染過程采用模板和上下文的中間表示,并將其轉(zhuǎn)換為可以提供給客戶端的最終字節(jié)流。— Django 文檔
REST框架包括許多內(nèi)置的Renderer類,它們允許你使用各種媒體類型返回響應(yīng)。還支持定義你自己的自定義渲染器,這樣可以靈活地設(shè)計(jì)你自己的媒體類型。
視圖的有效渲染器集合始終被定義為一個元素都是類的列表。當(dāng)輸入視圖時,REST框架將對傳入請求執(zhí)行內(nèi)容協(xié)商,并確定最適合的渲染器來滿足請求。
內(nèi)容協(xié)商的基本過程包括檢查請求的Accept頭,以確定響應(yīng)中期望的媒體類型。URL上可選的格式后綴可以用于顯式請求特定表示。例如URLhttp://example.com/api/users_count.json可能是始終返回JSON數(shù)據(jù)的路徑。
有關(guān)詳細(xì)信息,請參閱有關(guān)內(nèi)容協(xié)商的文檔。
可以使用DEFAULT_RENDERER_CLASSES設(shè)置全局默認(rèn)的渲染器集。例如,以下設(shè)置將使用JSON作為主要媒體類型,并且還包括自描述API。
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
)
}
你還可以設(shè)置用于單個視圖或視圖集的渲染器,使用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):
"""
返回JSON格式活動用戶數(shù)的視圖。
"""
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):
"""
返回JSON格式活動用戶數(shù)的視圖。
"""
user_count = User.objects.filter(active=True).count()
content = {'user_count': user_count}
return Response(content)
指定你的API的渲染器類時要考慮到每個媒體類型要分配哪些優(yōu)先級,這一點(diǎn)非常重要。如果一個客戶端不能指定它可以接受的表示形式,例如發(fā)送一個Accept: */*頭,或者不包含一個Accept頭,那么REST框架將選擇列表中用于響應(yīng)的第一個渲染器。
例如,如果你的API提供JSON響應(yīng)和HTML可瀏覽的API,則可能需要將JSONRenderer設(shè)置為你的默認(rèn)渲染器,以便向不指定Accept標(biāo)頭的客戶端發(fā)送JSON響應(yīng)。
如果你的API包含可以根據(jù)請求提供常規(guī)網(wǎng)頁和API響應(yīng)的視圖,那么你就可以考慮使用TemplateHTMLRenderer作為你的默認(rèn)渲染器,以便能在那些發(fā)送破壞的接收頭的舊版本的瀏覽器上能很好的展示。
使用utf-8編碼將請求的數(shù)據(jù)渲染成JSON。
請注意,默認(rèn)樣式是包括unicode字符,并使用沒有不必要空格的緊湊樣式渲染響應(yīng):
{"unicode black star":"★","value":999}
客戶端還可以包含'indent'媒體類型參數(shù),在這種情況下,返回的JSON將被縮進(jìn)。例如Accept: application/json; indent=4。
{
"unicode black star": "★",
"value": 999
}
可以使用UNICODE_JSON和COMPACT_JSON更改默認(rèn)JSON編碼樣式。
.media_type: application/json
.format: '.json'
.charset: None
使用Django的標(biāo)準(zhǔn)模板將數(shù)據(jù)渲染成HTML。
與其他渲染器不同,傳遞給Response的數(shù)據(jù)不需要序列化。此外,與其他渲染器不同,你可能希望在創(chuàng)建Response時包含一個template_name參數(shù)。
TemplateHTMLRenderer將創(chuàng)建一個RequestContext,使用response.data作為上下文字典,并確定用于渲染上下文的模板名稱。
模板名稱由(按優(yōu)先順序)確定:
使用 TemplateHTMLRenderer的視圖的例子:
class UserDetail(generics.RetrieveAPIView):
"""
返回給定用戶的模板HTML表示的視圖。
"""
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框架的常規(guī)HTML頁面,或者從單個路徑返回HTML和API響應(yīng)。
如果你正在構(gòu)建使用 TemplateHTMLRenderer 和其他渲染類的網(wǎng)站,你應(yīng)該考慮將TemplateHTMLRenderer列為renderer_classes列表中的第一個類,這樣即使對于發(fā)送格式不正確的ACCEPT:頭文件的瀏覽器它也將被優(yōu)先排序。
.media_type: text/html
.format: '.html'
.charset: utf-8
也可以看看: StaticHTMLRenderer
一個簡單的渲染器,只需返回預(yù)渲染的HTML。與其他渲染器不同,傳遞給響應(yīng)對象的數(shù)據(jù)應(yīng)該是表示要返回的內(nèi)容的字符串。
一個使用 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框架返回常規(guī)HTML頁面,也可以從單個路徑返回HTML和API響應(yīng)。
.media_type: text/html
.format: '.html'
.charset: utf-8
也可以看看: TemplateHTMLRenderer
將數(shù)據(jù)渲染成可瀏覽的API:
此渲染器將確定哪個其他渲染器將被賦予最高優(yōu)先級,并使用它在HTML頁面中顯示API。
.media_type: text/html
.format: '.api'
.charset: utf-8
.template: 'rest_framework/api.html'
默認(rèn)情況下,響應(yīng)內(nèi)容將以與BrowsableAPIRenderer不同的最高優(yōu)先級渲染器渲染。如果你需要自定義此行為,例如使用HTML作為默認(rèn)返回格式,但在可瀏覽的API中使用JSON,則可以通過重寫get_default_renderer()方法來實(shí)現(xiàn)。例如:
class CustomBrowsableAPIRenderer(BrowsableAPIRenderer):
def get_default_renderer(self, view):
return JSONRenderer()
將數(shù)據(jù)渲染給HTML以進(jìn)行類似管理的顯示:
此渲染器適用于CRUD風(fēng)格的Web API,還應(yīng)提供用于管理數(shù)據(jù)的用戶友好界面。
請注意,包含嵌套或列表序列化器的輸入視圖對于AdminRenderer將無法正常工作,因?yàn)镠TML表單無法正確支持它們。
注意: 當(dāng)數(shù)據(jù)中存在正確配置的URL_FIELD_NAME(缺省url)屬性時,AdminRenderer才能夠包含指向詳細(xì)頁面的鏈接。對于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'
將序列化程序返回的數(shù)據(jù)渲染為HTML表單。此渲染器的輸出不包括封閉的<form>標(biāo)簽,隱藏的CSRF輸入或任何提交按鈕。
此渲染器不是直接使用,而是可以通過將序列化器實(shí)例傳遞給render_form模板標(biāo)記來替代模板。
{% 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'
此渲染器用于渲染HTML multipart表單數(shù)據(jù)。 它不適合作為響應(yīng)渲染器,而是用于創(chuàng)建測試請求,使用REST framework的 測試客戶端和測試請求工廠。
.media_type: multipart/form-data; boundary=BoUnDaRyStRiNg
.format: '.multipart'
.charset: utf-8
要實(shí)現(xiàn)自定義渲染器,你應(yīng)該重寫B(tài)aseRenderer,設(shè)置 .media_type和.format屬性,并且實(shí)現(xiàn) .render(self, data, media_type=None, renderer_context=None) 方法。
這個方法應(yīng)當(dāng)返回一個字節(jié)bytestring,它將被用于HTTP響應(yīng)的主體。
傳遞給 .render() 方法的參數(shù)是:
請求數(shù)據(jù),由 Response() 實(shí)例化設(shè)置。
可選的。如果提供,這是由內(nèi)容協(xié)商階段確定的所接受的媒體類型。
根據(jù)客戶端的 Accept: 頭,這可能比渲染器的 media_type 屬性更具體,可能包括媒體類型參數(shù)。例如 "application/json; nested=true"。
可選的。如果提供,這是一個由view提供的上下文信息的字典。
默認(rèn)情況下這個字典會包括以下鍵: view, request, response, args, kwargs。
下面是一個示例明文渲染器,它將使用參數(shù)作為響應(yīng) data 的內(nèi)容返回響應(yīng)。
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)
假設(shè)默認(rèn)的渲染器類正在使用 UTF-8 編碼。要使用其他編碼,請?jiān)阡秩酒髟O(shè)置 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字符串,則響應(yīng)內(nèi)容將被Response類強(qiáng)制轉(zhuǎn)換成bytestring,渲染器上的設(shè)置的 charset 屬性將用于確定編碼。
如果渲染器返回一個bytestring表示原始的二進(jìn)制內(nèi)容,則應(yīng)該設(shè)置字符集的值為 None,確保響應(yīng)請求頭的 Content-Type 中不會設(shè)置 charset 值。
在某些情況下你可能還需要將 render_style 屬性設(shè)置成 'binary'。這么做也將確保可瀏覽的API不會嘗試將二進(jìn)制內(nèi)容顯示為字符串。
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的渲染器做一些非常靈活的事情。一些例子...
在某些情況下,你可能希望視圖根據(jù)所接受的媒體類型使用不同的序列化樣式。如果你需要實(shí)現(xiàn)這個功能,你可以根據(jù) request.accepted_renderer 來確定將用于響應(yīng)的協(xié)商渲染器。
例如:
@api_view(('GET',))
@renderer_classes((TemplateHTMLRenderer, JSONRenderer))
def list_users(request):
"""
一個可以返回系統(tǒng)中用戶的JSON或HTML表示的視圖。
"""
queryset = Users.objects.filter(active=True)
if request.accepted_renderer.format == 'html':
# TemplateHTMLRenderer 采用一個上下文的字典,
# 并且額外需要一個 'template_name'。
# 它不需要序列化。
data = {'users': queryset}
return Response(data, template_name='list_users.html')
# JSONRenderer 需要正常的序列化數(shù)據(jù)。
serializer = UserSerializer(instance=queryset)
data = serializer.data
return Response(data)
在某些情況下你可能希望渲染器提供一些列媒體類型。 在這種情況下,你可以通過為 media_type 設(shè)置諸如 image/* 或 */*這樣的值來指定應(yīng)該響應(yīng)的媒體類型。
如果你指定了渲染器的媒體類型,你應(yīng)該確保在返回響應(yīng)時使用 content_type 屬性明確指定媒體類型。 例如:
return Response(data, content_type='image/png')
許多Web API的目標(biāo),簡單的具有超鏈接的 JSON 響應(yīng)可能就已經(jīng)足夠了。如果你想完全擁抱RESTful設(shè)計(jì)和HATEOAS則需要更詳細(xì)地考慮媒體類型的設(shè)計(jì)和使用。
用Roy Fielding的話來說,"REST API 應(yīng)該花費(fèi)所有的描述性努力來定義用于表示資源和驅(qū)動應(yīng)用程序狀態(tài)的媒體類型(們),或者為現(xiàn)有的標(biāo)準(zhǔn)媒體類型定義擴(kuò)展關(guān)系名稱和/或超文本啟用標(biāo)記。"。
有關(guān)自定義媒體類型的優(yōu)秀示例,請參閱GitHub關(guān)于自定義 application/vnd.github+json 媒體類型的應(yīng)用以及 Mike Amundsen的IANA認(rèn)可的 application/vnd.collection+json JSON超媒體。
通常渲染器都具有相同的行為,無論它處理的是正常的響應(yīng)還是由異常引起的響應(yīng),如 Http404 或 PermissionDenied 異常,或者一個 APIException 的子類。
如果你正在使用 TemplateHTMLRenderer 或 StaticHTMLRenderer 時拋出了異常,行為略有不同。并且反映 Django對錯誤視圖的默認(rèn)處理.
由HTML渲染器引發(fā)和處理的異常將嘗試按照優(yōu)先順序使用以下方法之一進(jìn)行渲染。
模板們將使用一個包括status_code和details的 RequestContext 渲染。
注意: 如果設(shè)置了 DEBUG=True,Django將展示它的標(biāo)準(zhǔn)回溯錯誤頁面而不是渲染HTTP狀態(tài)碼和文本。
以下第三方包都是可用的。
REST framework YAML 提供 YAML 解析和渲染支持。它之前直接包含在REST framework 包中,現(xiàn)在被替代為第三方包支持。
使用pip安裝。
$ pip install djangorestframework-yaml
修改你的REST framework設(shè)置。
REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES': (
'rest_framework_yaml.parsers.YAMLParser',
),
'DEFAULT_RENDERER_CLASSES': (
'rest_framework_yaml.renderers.YAMLRenderer',
),
}
REST Framework XML 提供了一個簡單的非正式XML格式。它之前直接包含在REST framework 包中,現(xiàn)在被替代為第三方包支持。
使用pip安裝。
$ pip install djangorestframework-xml
修改你的REST framework設(shè)置。
REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES': (
'rest_framework_xml.parsers.XMLParser',
),
'DEFAULT_RENDERER_CLASSES': (
'rest_framework_xml.renderers.XMLRenderer',
),
}
REST framework JSONP 提供JSONP渲染支持。它之前直接包含在REST framework 包中,現(xiàn)在被替代為第三方包支持。
警告: 如果你需要跨域的AJAX請求,你通常應(yīng)該使用更現(xiàn)代化的CORS方法代替JSONP。更多詳細(xì)信息請參閱CORS文檔。
jsonp 本質(zhì)上是一個瀏覽器hack方法,僅適用于全局可讀的API路徑,其中GET請求未經(jīng)身份驗(yàn)證,并且不需要任何用戶權(quán)限。
使用pip安裝。
$ pip install djangorestframework-jsonp
修改你的REST framework設(shè)置。
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': (
'rest_framework_jsonp.renderers.JSONPRenderer',
),
}
MessagePack是一種快速,高效的二進(jìn)制序列化格式。Juan Riaza維護(hù)著djangorestframework-msgpack 包,它為REST framework提供MessagePack渲染器和解析器支持。
逗號分隔的值是純文本數(shù)據(jù)格式,可以輕松導(dǎo)入到電子表格應(yīng)用中。Mjumbe Poe維護(hù)著djangorestframework-csv包,它為REST framework提供了CSV渲染器支持。
UltraJSON是一個優(yōu)化的C JSON編碼器,可以顯著提高JSON渲染速度。Jacob Haslehurst維護(hù)著使用UJSON包實(shí)現(xiàn)JSON渲染的drf-ujson-renderer包。
djangorestframework-camel-case為REST framework提供了駝峰樣式的JSON渲染器和解析器。這使序列化程序可以使用Python風(fēng)格的下劃線字段名,但是在API中顯示成Javascript樣式的駝峰字段名。它被Vitaly Babiy維護(hù)著。
Django REST Pandas提供了一個序列化器和渲染器,通過Pandas DataFrame API提供額外的數(shù)據(jù)處理和輸出。Django REST Pandas包括Pandas風(fēng)格的CSV文件,Excel表格(包括 .xls 和 .xlsx)以及許多其他格式的渲染器。作為wq 項(xiàng)目的一部分由S. Andrew Sheppard維護(hù)著。
Rest Framework Latex提供了一個使用Laulatex輸出PDF的渲染器。它由Pebble (S/F Software)維護(hù)著。
更多建議: