本文へスキップ
hdknr blog
戻る

DRF: Content Negotiation

更新日:

DRF: Content Negotiation

DefaultContentNegotiation

content_negotiation_classをカスタマイズするには、以下のようにします。

from rest_framework.negotiation import DefaultContentNegotiation

class MyContentNegotiation(DefaultContentNegotiation):
    def select_renderer(self, request, renderers, format_suffix=None):
        # ここに処理を書きます。
        pass

上記の例では、DefaultContentNegotiationを継承しています。

select_renderer()メソッドには、レンダラーを選択するための処理を書きます。 このメソッドは、リクエストオブジェクト、レンダラーのリスト、およびフォーマットサフィックスを引数として受け取ります。

ソース: Bing との会話 2023/5/12

ViewSetでの設定

ViewSetごとにcontent_negotiation_classを設定することができます。

以下のように、ViewSetクラスのcontent_negotiation_class属性にカスタムクラスを指定します。

from rest_framework.viewsets import ModelViewSet

class MyViewSet(ModelViewSet):
    queryset = MyModel.objects.all()
    serializer_class = MySerializer
    content_negotiation_class = MyContentNegotiation

上記の例では、MyContentNegotiationというカスタムクラスを使用しています。このクラスは、前回の回答で紹介したものです。

バイナリファイルの処理

バイナリレンダラ:

from rest_framework_csv import renderers

class BinaryRenderer(renderers.BaseRenderer):
    def render(self, data, media_type=None, renderer_context=None):
        return data

ネゴシエータ:

from rest_framework.negotiation import DefaultContentNegotiation
from mimetypes import guess_type

class AttachmentContentNegotiation(DefaultContentNegotiation):
    def select_renderer(self, request, renderers, format_suffix=None):
        try:
            res = super().select_renderer(request, renderers, format_suffix=format_suffix)
            return res
        except Exception as e:
            mt = format_suffix and guess_type(f"a.{format_suffix}")[0]
            logger.info(f"{e}:BinaryRenderer for {format_suffix}")
            return (base_renderers.BinaryRenderer(), mt)
class AttachmentViewSet(viewsets.BaseModelViewSet):
    permission_classes = [
        permissions.AttachmentPermission,
    ]
    filterset_class = filters.AttachmentFilter
    serializer_class = serializers.AttachmentSerializer
    queryset = models.Attachment.objects.order_by("id")
    pagination_class = paginations.Pagination
    content_negotiation_class = AttachmentContentNegotiation


前の記事
pandas: カラム連結
次の記事
Django Subquery