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