renderers.py

レンダラー

TemplateResponseインスタンスをクライアントに返す前に、レンダリングする必要があります。レンダリングプロセスでは、テンプレートとコンテキストの中間表現を取得し、クライアントに提供できる最終的なバイトストリームに変換します。

Djangoドキュメント

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}

テンプレート名は、(優先順位の順に)次のように決定されます

  1. 応答に渡される明示的なtemplate_name引数。
  2. このクラスに設定された明示的な.template_name属性。
  3. 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にレンダリングします

The BrowsableAPIRenderer

このレンダラーは、どの他のレンダラーが最優先順位を与えられたかを確認し、それを使用して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にレンダリングします

The AdminRender view

このレンダラーは、データを管理するためのユーザーフレンドリーなインターフェイスも提供する必要がある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

オプション。提供されている場合、これはビューによって提供されるコンテキスト情報の辞書です。

デフォルトでは、これにはviewrequestresponseargskwargsのキーが含まれます。

以下は、レスポンスの内容として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エラービュー

通常、レンダラーは、通常のレスポンスを処理している場合でも、Http404PermissionDenied例外、または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 AllenThe 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 Sheppardwq Projectの一部として管理しています。

LaTeX

Rest Framework Latexは、Laulatexを使用してPDFを出力するレンダラーを提供します。Pebble(S / F Software)によって管理されています。