When using serializer
of django-rest-framework
to dynamically change fields in response to client requests
You can return by using the class in the official guide.
This is a sample call from the view set. Here, only the field is dynamically changed, but by combining it with other parameters, the returned field can be changed flexibly.
Use the classes in the official guide. 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)
It is a model with a simple code and 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='code', help_text='code', max_length=10)
name = models.CharField(verbose_name='name', help_text='name', max_length=50)
class CustomerSerializer(DynamicFieldsModelSerializer):
class Meta:
model = Customer
fields = (
'id',
'code',
'name',
)
Override get_serializer
with the field value set in the query string only on GET
requests
Dynamically change the columns to 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
is specified in the fieldcurl -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"
}
]