レンダラー
TemplateResponseインスタンスをクライアントに返す前に、レンダリングする必要があります。レンダリングプロセスでは、テンプレートとコンテキストの中間表現を取得し、クライアントに提供できる最終的なバイトストリームに変換します。
REST frameworkには、さまざまなメディアタイプで応答を返すことができる多数の組み込みRendererクラスが含まれています。独自のメディアタイプを柔軟に設計できるように、独自のカスタムレンダラーを定義するためのサポートも用意されています。
レンダラーがどのように決定されるか
ビューの有効なレンダラーのセットは、常にクラスのリストとして定義されます。ビューが入力されると、REST frameworkは受信リクエストでコンテンツネゴシエーションを実行し、リクエストを満たすのに最適なレンダラーを決定します。
コンテンツネゴシエーションの基本プロセスでは、リクエストのAccept
ヘッダーを調べて、レスポンスでどのメディアタイプが予期されているかを判断します。オプションで、URLのフォーマットサフィックスを使用して、特定の表現を明示的に要求できます。たとえば、URLhttp://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_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を提供する場合は、Accept
ヘッダーを指定しないクライアントにJSON
レスポンスを送信するために、JSONRenderer
をデフォルトのレンダラーにすることをお勧めします。
APIにリクエストに応じて通常のWebページとAPIレスポンスの両方を提供できるビューが含まれている場合は、壊れたacceptヘッダーを送信する古いブラウザーとうまく動作するように、TemplateHTMLRenderer
をデフォルトのレンダラーにすることを検討してください。
APIリファレンス
JSONRenderer
リクエストデータをutf-8エンコーディングを使用してJSON
にレンダリングします。
デフォルトのスタイルは、Unicode文字を含め、不要な空白のないコンパクトなスタイルを使用して応答をレンダリングすることに注意してください。
{"unicode black star":"★","value":999}
クライアントは、追加で'indent'
メディアタイプのパラメーターを含めることができます。この場合、返されるJSON
はインデントされます。たとえば、Accept: application/json; indent=4
です。
{
"unicode black star": "★",
"value": 999
}
デフォルトのJSONエンコードスタイルは、UNICODE_JSON
およびCOMPACT_JSON
設定キーを使用して変更できます。
.media_type: application/json
.format: 'json'
.charset: None
TemplateHTMLRenderer
Djangoの標準テンプレートレンダリングを使用して、データをHTMLにレンダリングします。他のレンダラーとは異なり、Response
に渡されるデータをシリアル化する必要はありません。また、他のレンダラーとは異なり、Response
を作成するときにtemplate_name
引数を含めることができます。
TemplateHTMLRendererは、response.data
をコンテキスト辞書として使用してRequestContext
を作成し、コンテキストのレンダリングに使用するテンプレート名を決定します。
注: シリアライザーを使用するビューで使用する場合、レンダリング用に送信されるResponse
は辞書ではない可能性があり、TemplateHTMLRenderer
がレンダリングできるように、返す前に辞書でラップする必要があります。例
response.data = {'results': 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ページを返すか、単一のエンドポイントからHTMLとAPIの両方の応答を返すことができます。
TemplateHTMLRenderer
を他のレンダラークラスと一緒に使用するWebサイトを構築している場合は、renderer_classes
リストの最初のクラスとしてTemplateHTMLRenderer
をリストすることを検討してください。これにより、不適切な形式のACCEPT:
ヘッダーを送信するブラウザーでも最初に優先順位が付けられます。
TemplateHTMLRenderer
の使用法の詳細については、HTMLとフォームトピックページを参照してください。
.media_type: text/html
.format: 'html'
.charset: utf-8
参照: 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 frameworkを使用して通常のHTMLページを返すか、単一のエンドポイントからHTMLとAPIの両方の応答を返すことができます。
.media_type: text/html
.format: 'html'
.charset: utf-8
参照: TemplateHTMLRenderer
BrowsableAPIRenderer
ブラウズ可能なAPI用にデータをHTMLにレンダリングします
このレンダラーは、どの他のレンダラーが最優先順位を与えられたかを確認し、それを使用して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()
AdminRenderer
管理者のような表示のためにデータをHTMLにレンダリングします
このレンダラーは、データを管理するためのユーザーフレンドリーなインターフェイスも提供する必要があるCRUDスタイルのWeb APIに適しています。
入力にネストされたシリアライザーまたはリストシリアライザーがあるビューは、HTMLフォームがそれらを適切にサポートできないため、AdminRenderer
ではうまく機能しないことに注意してください。
注: AdminRenderer
は、適切に構成されたURL_FIELD_NAME
(デフォルトではurl
)属性がデータに存在する場合にのみ、詳細ページへのリンクを含めることができます。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 & フォームのドキュメントを参照してください。
.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, accepted_media_type=None, renderer_context=None)
メソッドを実装する必要があります。
このメソッドは、HTTPレスポンスのボディとして使用されるバイト文字列を返す必要があります。
.render()
メソッドに渡される引数は以下のとおりです。
data
Response()
のインスタンス化によって設定されたリクエストデータ。
accepted_media_type=None
オプション。提供されている場合、これはコンテンツネゴシエーション段階で決定された受け入れ可能なメディアタイプです。
クライアントのAccept:
ヘッダーに応じて、これはレンダラーの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, accepted_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, accepted_media_type=None, renderer_context=None):
return data.encode(self.charset)
レンダラークラスがユニコード文字列を返す場合、レスポンスコンテンツはResponse
クラスによってバイト文字列に強制変換され、レンダラーに設定されたcharset
属性を使用してエンコーディングが決定されることに注意してください。
レンダラーが生のバイナリコンテンツを表すバイト文字列を返す場合は、charset
値をNone
に設定する必要があります。これにより、レスポンスのContent-Type
ヘッダーにcharset
値が設定されなくなります。
場合によっては、render_style
属性を'binary'
に設定することもできます。これにより、ブラウザブルAPIがバイナリコンテンツを文字列として表示しようとしなくなることも保証されます。
class JPEGRenderer(renderers.BaseRenderer):
media_type = 'image/jpeg'
format = 'jpg'
charset = None
render_style = 'binary'
def render(self, data, accepted_media_type=None, renderer_context=None):
return data
高度なレンダラーの使用法
REST frameworkのレンダラーを使用すると、非常に柔軟なことができます。いくつかの例を挙げます...
- 要求されたメディアタイプに応じて、同じエンドポイントからフラット表現またはネストされた表現を提供します。
- 同じエンドポイントから、通常のHTML WebページとJSONベースのAPIレスポンスの両方を提供します。
- APIクライアントが使用できる複数のタイプのHTML表現を指定します。
media_type = 'image/*'
のように、レンダラーのメディアタイプを明示的に指定せずに、Accept
ヘッダーを使用してレスポンスのエンコーディングを変化させます。
メディアタイプによる動作の変更
場合によっては、受け入れられたメディアタイプに応じて、ビューが異なるシリアライズスタイルを使用したい場合があります。これが必要な場合は、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)
メディアタイプの指定不足
場合によっては、レンダラーにさまざまなメディアタイプを提供させたい場合があります。この場合、image/*
や*/*
のようなmedia_type
値を使用して、応答する必要があるメディアタイプを明示的に指定せずに設定できます。
レンダラーのメディアタイプを明示的に指定しない場合は、content_type
属性を使用して、レスポンスを返すときにメディアタイプを明示的に指定する必要があります。例えば
return Response(data, content_type='image/png')
メディアタイプの設計
多くのWeb APIの目的では、ハイパーリンク関係を持つ単純なJSON
レスポンスで十分な場合があります。完全にRESTfulな設計とHATEOASを採用したい場合は、メディアタイプの設計と使用法をより詳細に検討する必要があります。
Roy Fieldingの言葉では、「REST APIは、リソースの表現とアプリケーションの状態を駆動するために使用されるメディアタイプの定義、または既存の標準メディアタイプのための拡張された関係名やハイパーテキスト対応のマークアップの定義に、その記述的な努力のほとんどを費やすべきです。」。
カスタムメディアタイプの良い例としては、GitHubが使用するカスタムのapplication/vnd.github+jsonメディアタイプや、Mike AmundsenのIANA承認済みapplication/vnd.collection+json JSONベースのハイパーメディアがあります。
HTMLエラービュー
通常、レンダラーは、通常のレスポンスを処理している場合でも、Http404
やPermissionDenied
例外、またはAPIException
のサブクラスなど、例外が発生したことによるレスポンスを処理している場合でも、同じように動作します。
TemplateHTMLRenderer
またはStaticHTMLRenderer
のいずれかを使用している場合に例外が発生すると、動作がわずかに異なり、Djangoのエラービューのデフォルトの処理を反映します。
HTMLレンダラーによって発生および処理された例外は、次の優先順位で、次のいずれかの方法を使用してレンダリングしようとします。
{status_code}.html
という名前のテンプレートを読み込んでレンダリングします。api_exception.html
という名前のテンプレートを読み込んでレンダリングします。- HTTPステータスコードとテキスト(例: "404 Not Found")をレンダリングします。
テンプレートは、status_code
キーとdetails
キーを含むRequestContext
でレンダリングされます。
注: DEBUG=True
の場合、HTTPステータスコードとテキストをレンダリングする代わりに、Djangoの標準トレースバックエラーページが表示されます。
サードパーティパッケージ
以下のサードパーティパッケージも利用できます。
YAML
REST framework YAMLは、YAMLの解析とレンダリングのサポートを提供します。以前はREST frameworkパッケージに直接含まれていましたが、現在はサードパーティパッケージとしてサポートされています。
インストールと設定
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 frameworkパッケージに直接含まれていましたが、現在はサードパーティパッケージとしてサポートされています。
インストールと設定
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 frameworkパッケージに直接含まれていましたが、現在はサードパーティパッケージとしてサポートされています。
警告: クロスドメインAJAXリクエストが必要な場合は、一般的に、JSONP
の代替としてCORSの最新のアプローチを使用する必要があります。詳細については、CORSドキュメントを参照してください。
jsonp
アプローチは本質的にブラウザハックであり、GET
リクエストが認証されておらず、ユーザー権限を必要としないグローバルに読み取り可能なAPIエンドポイントにのみ適しています。
インストールと設定
pipを使用してインストールします。
$ pip install djangorestframework-jsonp
REST frameworkの設定を変更します。
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': [
'rest_framework_jsonp.renderers.JSONPRenderer',
],
}
MessagePack
MessagePackは、高速で効率的なバイナリシリアライゼーション形式です。Juan Riazaは、REST framework用のMessagePackレンダラーとパーサーのサポートを提供するdjangorestframework-msgpackパッケージを管理しています。
Microsoft Excel: XLSX(バイナリスプレッドシートエンドポイント)
XLSXは、世界で最も人気のあるバイナリスプレッドシート形式です。Tim Allen(The Wharton School)は、OpenPyXLを使用してエンドポイントをXLSXスプレッドシートとしてレンダリングし、クライアントがダウンロードできるようにするdrf-excelを管理しています。スプレッドシートは、ビューごとにスタイルを設定できます。
インストールと設定
pipを使用してインストールします。
$ pip install drf-excel
REST frameworkの設定を変更します。
REST_FRAMEWORK = {
...
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
'drf_excel.renderers.XLSXRenderer',
],
}
ファイル名なしでファイルがストリーミングされるのを防ぐため(ブラウザはしばしばファイル名を拡張子なしの「download」にデフォルト設定します)、Content-Disposition
ヘッダーをオーバーライドするためにmixinを使用する必要があります。ファイル名が提供されていない場合、デフォルトはexport.xlsx
になります。例えば
from rest_framework.viewsets import ReadOnlyModelViewSet
from drf_excel.mixins import XLSXFileMixin
from drf_excel.renderers import XLSXRenderer
from .models import MyExampleModel
from .serializers import MyExampleSerializer
class MyExampleViewSet(XLSXFileMixin, ReadOnlyModelViewSet):
queryset = MyExampleModel.objects.all()
serializer_class = MyExampleSerializer
renderer_classes = [XLSXRenderer]
filename = 'my_export.xlsx'
CSV
カンマ区切り値は、スプレッドシートアプリケーションに簡単にインポートできるプレーンテキストの表形式データ形式です。Mjumbe Poeは、REST framework用のCSVレンダラーサポートを提供するdjangorestframework-csvパッケージを管理しています。
UltraJSON
UltraJSONは、JSONレンダリングを大幅に高速化できる最適化されたC JSONエンコーダーです。Adam Mertzは、現在メンテナンスされていないdrf-ujson-rendererのフォークであるdrf_ujson2を管理しており、UJSONパッケージを使用してJSONレンダリングを実装しています。
CamelCase JSON
djangorestframework-camel-caseは、REST framework用のキャメルケースJSONレンダラーとパーサーを提供します。これにより、シリアライザーはPythonスタイルのアンダースコア付きフィールド名を使用できますが、APIではJavascriptスタイルのキャメルケースフィールド名として公開されます。Vitaly Babiyによって管理されています。
Pandas (CSV, Excel, PNG)
Django REST Pandasは、Pandas DataFrame APIを介した追加のデータ処理と出力をサポートするシリアライザーとレンダラーを提供します。Django REST Pandasには、PandasスタイルのCSVファイル、Excelワークブック(.xls
と.xlsx
の両方)、およびその他の多くの形式のレンダラーが含まれています。これはS. Andrew Sheppardがwq Projectの一部として管理しています。
LaTeX
Rest Framework Latexは、Laulatexを使用してPDFを出力するレンダラーを提供します。Pebble(S / F Software)によって管理されています。