Django Rest Framework - How to use url parameters in API requests to exclude fields in response
Let's say I have an API that returns some simple list of objects at the /users
endpoint
{
"count": 42,
"results": [
{
"name": "David",
"age": 30,
"location": "Alaska"
},
...
]
}
I would like to pass a simple boolean that changes the output by removing a field.
So /users?abridged=True
would return the same objects, but omit a field.
{
"count": 42,
"results": [
{
"name": "David",
"age": 30,
},
...
]
}
I suppose I could create two serializers, one for the full version and one abridged, but I'm not sure how I could use a url parameter to select which serializer to use. Is there a better way to do this?
One way is to override list
method and modify fields dynamically based on the presence of the query string param:
views.py
class UserViewSet(viewsets.ModelViewSet):
User = get_user_model()
queryset = User.objects.all()
serializer_class = UserSerializer
def list(self, request):
abridged = request.GET.get('abridged', None)
if abridged:
fields = ('username', 'age',)
else:
fields = ('username', 'age', 'location')
serializer = UserListSerializer(
{'count': self.get_queryset().count()},
context={'fields': fields, 'qs': self.get_queryset()}
)
return Response(serializer.data)
Note that I used a "wrapper"
serializer for the list method in order to obtain the desired output. Using extra context to pass data for its SerializerMethodField.
serializers.py
class DynamicFieldsModelSerializer(serializers.ModelSerializer):
...
class UserSerializer(DynamicFieldsModelSerializer):
class Meta:
model = get_user_model()
fields = ['username', 'age', 'location']
class UserListSerializer(serializers.Serializer):
count = serializers.IntegerField()
results = serializers.SerializerMethodField()
def get_results(self, obj):
serializer = UserSerializer(self.context['qs'], many=True, fields=self.context['fields'])
return serializer.data