Django REST framework API 指南(1):請求
Django REST framework API 指南(2):響應
Django REST framework API 指南(3):視圖
Django REST framework API 指南(4):通用視圖
Django REST framework API 指南(5):視圖集
Django REST framework API 指南(6):路由
Django REST framework API 指南(7):解析
Django REST framework API 指南(8):渲染html
官方原文連接python
REST framework 包含許多內置的渲染器類,容許您使用各類 media type 返回響應。同時也支持自定義渲染器。django
視圖的渲染器集合始終被定義爲類列表。當調用視圖時,REST framework 將對請求內容進行分析,並肯定最合適的渲染器以知足請求。內容分析的基本過程包括檢查請求的 Accept
header,以肯定它在響應中指望的 media type。或者,用 URL 上的格式後綴明確表示。例如,URL http://example.com/api/users_count.json
可能始終返回 JSON 數據。json
可使用 DEFAULT_RENDERER_CLASSES
設置全局的默認渲染器集。例如,如下設置將使用JSON做爲主要 media type,而且還包含自描述 API。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
裝飾器的函數視圖上設置。app
@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:*/*
header,或者根本不包含 Accept
header,則 REST framework 將選擇列表中的第一個渲染器用於響應。ide
例如,若是你的 API 提供 JSON 響應和可瀏覽的 HTML API,則可能須要將 JSONRenderer
做爲默認渲染器,以便將 JSON
響應發送給未指定 Accept
header 的客戶端。函數
若是你的 API 包含可根據請求同時處理常規網頁和 API 響應的視圖,那麼你能夠考慮將 TemplateHTMLRenderer
設置爲默認渲染器,以便與發送 broken accept headers 的老式瀏覽器很好地配合使用。post
使用 utf-8 編碼將請求數據呈現爲 JSON
。
請注意,默認風格包含 unicode 字符,並使用緊湊風格呈現(沒有多餘的空白)響應:
{"unicode black star":"★","value":999}
複製代碼
客戶端可能還會包含 「縮進」 media type 參數,在這種狀況下,返回的 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
的數據不須要序列化。另外,建立 Response
時可能須要包含 template_name
參數。
TemplateHTMLRenderer 將建立一個 RequestContext
,使用 response.data
做爲上下文字典,並肯定用於呈現上下文的模板名稱。
模板名稱由(按優先順序)肯定:
template_name
參數。.template_name
屬性。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 framework 返回常規 HTML 頁面,或者從單個端點(a single endpoint)返回 HTML 和 API 響應。
若是你正在構建使用 TemplateHTMLRenderer
以及其餘渲染器類的網站,則應考慮將 TemplateHTMLRenderer
列爲 renderer_classes
列表中的第一個類,以便即便對於發送格式錯誤的 ACCEPT:
header 的瀏覽器,也會優先考慮它。
.media_type: text/html
.format: '.html'
.charset: utf-8
一個簡單的渲染器,它只是返回預渲染的 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 framework 返回常規 HTML 頁面,或者從單個端點(a single endpoint)返回 HTML 和 API 響應。
.media_type: text/html
.format: '.html'
.charset: utf-8
將數據呈現爲可瀏覽的 HTML API:
該渲染器將肯定哪一個其餘渲染器被賦予最高優先級,並使用該渲染器在 HTML 頁面中顯示 API 風格響應。
.media_type: text/html
.format: '.api'
.charset: utf-8
.template: 'rest_framework/api.html'
自定義 BrowsableAPIRenderer
默認狀況下,除 BrowsableAPIRenderer
以外,響應內容將使用最高優先級的渲染器渲染。若是你須要自定義此行爲,例如,將 HTML 用做默認返回格式,但在可瀏覽的 API 中使用 JSON,則能夠經過覆蓋 get_default_renderer()
方法來實現。
例如:
class CustomBrowsableAPIRenderer(BrowsableAPIRenderer):
def get_default_renderer(self, view):
return JSONRenderer()
複製代碼
將數據呈現爲 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'
將序列化返回的數據呈現爲 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 form 數據。它不適合做爲響應渲染器,而是用於建立測試請求,使用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)
方法。
該方法應返回一個字符串,它將用做 HTTP 響應的主體。
傳遞給 .render()
方法的參數是:
data
請求數據,由 Response()
實例化時設置。
media_type=None
可選的。若是提供,這是接受的媒體類型,由內容協商(content negotiation)階段肯定。
依賴於客戶端的 Accept:
header,它能夠比渲染器的 media_type
屬性更具體,而且可能包含媒體類型參數。好比 "application/json; nested=true"
。
renderer_context=None
可選的。若是提供,它是視圖提供的上下文信息字典。
默認狀況下,這將包括如下鍵:view
, request
, response
, args
, kwargs
。
如下是一個示例純文本渲染器,它將返回帶有數據參數的響應做爲響應的內容。
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
屬性用於肯定編碼。
若是渲染器返回表明原始二進制內容的字符串,則應將 charset
值設置爲 None
,這將確保響應的 Content-Type
header 不會設置 charset
值。
在某些狀況下,你可能還想將 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 的渲染器來作一些很是靈活的事情。例如...
media_type ='image/*'
,並使用 Accept
header 改變響應的編碼。在某些狀況下,可能但願視圖根據接受的 media type 使用不一樣的序列化風格。若是須要這樣作,能夠訪問 request.accepted_renderer
以肯定將用於響應的協商(negotiate)渲染器。
例如:
@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 type 。在這種狀況下,能夠經過使用 media_type
值(如 image/*
或*/*
)來指定它應該響應的 media type 。
若是沒有明確指定渲染器的 media type ,則應確保在返回響應時使用 content_type
屬性明確指定 media type 。好比:
return Response(data, content_type='image/png')
複製代碼
出於許多 Web API 的目的,具備超連接關係的簡單 JSON 響應可能就足夠了。若是你想徹底融入 RESTful 設計和 HATEOAS,則須要更詳細地考慮 media type 的設計和使用。
一般狀況下,不管處理常規響應仍是引起異常的響應(例如 Http404
或 PermissionDenied
異常)或 APIException
的子類引發的響應,渲染器都會有相同的表現。
若是您使用的是 TemplateHTMLRenderer
或 StaticHTMLRenderer
,而且引起異常,則行爲會稍有不一樣,反映了 Django 對錯誤視圖的默認處理。
由 HTML 渲染器引起和處理的異常將嘗試使用如下方法之一(按優先順序)進行渲染。
{status_code}.html
。api_exception.html
。模板將使用 RequestContext
進行渲染,其中包含 status_code
和 details
鍵。
注意:若是
DEBUG = True
,則會顯示 Django 的標準錯誤回溯頁面,而不是顯示 HTTP 狀態碼和文本。