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
- (1) Content negotiation - Django REST framework. https://www.django-rest-framework.org/api-guide/content-negotiation/.
- (2) Django REST Framework - Content negotiation - HTTPは … https://runebook.dev/ja/docs/django_rest_framework/api-guide/content-negotiation/index.
- (3) Django REST framework カスタマイズ方法 - チュートリアルの補足. https://qiita.com/okoppe8/items/c58bb3faaf26c9e2f27f.
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