Django Rest Framework: Dynamically return subset of fields

django, django-rest-framework

Solution

You can override the serializer `__init__` method and set the `fields` attribute dynamically, based on the query params. You can access the `request` object throughout the context, passed to the serializer.

Here is a copy&paste from Django Rest Framework documentation example on the matter:

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):
        # Instantiate the superclass normally
        super(DynamicFieldsModelSerializer, self).__init__(*args, **kwargs)

        fields = self.context['request'].query_params.get('fields')
        if fields:
            fields = fields.split(',')
            # Drop any fields that are not specified in the `fields` argument.
            allowed = set(fields)
            existing = set(self.fields.keys())
            for field_name in existing - allowed:
                self.fields.pop(field_name)


class UserSerializer(DynamicFieldsModelSerializer, serializers.HyperlinkedModelSerializer):

    class Meta:
        model = User
        fields = ('url', 'username', 'email')

Problem

Problem As recommended in the blogpost Best Practices for Designing a Pragmatic RESTful API, I would like to add a `fields` query parameter to a Django Rest Framework based API which enables the user to select only a subset of fields per resource. Example Serializer: ``` class IdentitySerializer(serializers.HyperlinkedModelSerializer): class Meta: model = models.Identity fields = ('id', 'url', 'type', 'data') ``` A regular query would return all fields. `GET /identities/` ``` [ { "id": 1, "url": "http://localhost:8000/api/identities/1/", "type": 5, "data": "John Doe" }, ... ] ``` A query with the `fields` parameter should only return a subset of the fields: `GET /identities/?fields=id,data` ``` [ { "id": 1, "data": "John Doe" }, ... ] ``` A query with invalid fields should either ignore the invalid fields or throw a client error. Goal Is this possible out of the box somehow? If not, what's the simplest way to implement this? Is there a 3rd party package around that does this already?

Original source