creyD
creyD

Reputation: 2126

Is there a way in Django Rest Framework to deliver only specific attributes?

When building a large web backend we are faced with the problem that we have models with a lot of attributes. As we want to reduce the size of the responses for efficiency we use different serializers for our models. Take this simple model for instance:

class Address(models.Model):
    country_id = models.ForeignKey(Country, on_delete=models.PROTECT)
    postal_code = models.CharField(max_length=10)
    street = models.CharField(max_length=176)
    number = models.CharField(max_length=20)
    additional = models.CharField(max_length=256, blank=True, default='')
    city = models.CharField(max_length=176)
    state = models.CharField(max_length=50)

    user = models.ForeignKey('user.User', on_delete=models.CASCADE)

For this alone we have an ID Serializer, a StringSerializer (for delivering a usable string), a MinimalSerializer (for a list of multiple addresses), a DetailSerializer (with depth=1 for getting country and user details ...

Now with this complexity we face several issues and thought about restructuring the api to include the required fields in the request. Is this possible with django + drf? We believed to find something under Content Negotiation but this is a different topic.

Upvotes: 0

Views: 107

Answers (1)

Shayan
Shayan

Reputation: 338

You can dynamically modify fields like this:

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)

For more information visit drf docs.

Upvotes: 1

Related Questions