はじめに
django-rest-framework
のserializer
を利用してクライアントからのリクエストに応じて動的にフィールドを変更する場合、
公式ガイドにあるクラスを利用し返すことが出来ます。
ビューセットからの呼び出しサンプルです。
ここではフィールドの動的変更のみを行いますが、他のパラメータと組み合わせることで返却するフィールドを柔軟に変更できるようになります。
Dynamic クラスの定義
公式ガイドにあるクラスを利用します。
https://www.django-rest-framework.org/api-guide/serializers/#dynamically-modifying-fields
from rest_framework import serializers
class DynamicFieldsModelSerializer(serializers.ModelSerializer):
"""
A ModelSerializer that takes an additional `fields` argument that
controls which fields should be displayed.
"""
def __init__(self, *args, **kwargs):
# Don't pass the 'fields' arg up to the superclass
fields = kwargs.pop('fields', None)
# Instantiate the superclass normally
super(DynamicFieldsModelSerializer, self).__init__(*args, **kwargs)
if fields is not None:
# Drop any fields that are not specified in the `fields` argument.
allowed = set(fields)
existing = set(self.fields)
for field_name in existing - allowed:
self.fields.pop(field_name)
モデルの作成
シンプルなコード、名称を持つモデルです。
from uuid import uuid4
from django.db import models
class Customer(models.Model):
id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
code = models.CharField(verbose_name='コード', help_text='コード', max_length=10)
name = models.CharField(verbose_name='名称', help_text='名称', max_length=50)
シリアライザの作成
class CustomerSerializer(DynamicFieldsModelSerializer):
class Meta:
model = Customer
fields = (
'id',
'code',
'name',
)
ビューセットの作成
get_serializer
をオーバーライドし、GET
リクエスト時のみクエリ文字列に設定されたフィールド値で
取得する列を動的に変更します。
from rest_framework import viewsets
class CustomerViewSet(viewsets.ModelViewSet):
queryset = Customer.objects.all()
serializer_class = CustomerSerializer
def get_serializer(self, *args, **kwargs):
if self.action == 'list':
if 'fields[]' in self.request.query_params:
kwargs['fields'] = self.request.query_params.getlist('fields[]')
return super().get_serializer(*args, **kwargs)
動作確認
フィールドを指定しない場合
curl -s -X GET "http://localhost:18000/api/customers/" -H "accept: application/json" | jq .
[
{
"id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx1",
"code": "001",
"name": "test1"
},
{
"id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx2",
"code": "002",
"name": "test2"
}
]
フィールドにcode
, name
を指定した場合
curl -s -X GET "http://localhost:18000/api/customers/?fields[]=code&fields[]=name" --globoff -H "accept: application/json" | jq .
[
{
"code": "001",
"name": "test"
},
{
"code": "002",
"name": "test2"
}
]