Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to dynamically change depth in Django Rest Framework nested serializers?

I have a set of nested serializers which have a depth set on their respective Meta classes. I'd like to programmatically change the depth based on parameters passed into in views.

class ResourceSerializer(serializers.ModelSerializer):
    type         = serializers.PrimaryKeyRelatedField(queryset=EntityType.objects.all())
    tags         = serializers.PrimaryKeyRelatedField(queryset=Tag.objects.all(), many=True)

    class Meta:
        model  = Resource
        fields = ('id', 'type', 'uri', 'tags', 'created_date')
        depth = 1

Unfortunately, there doesn't seem to be a way to override the depth attribute at runtime. My current solution has been to inherit the "shallow" serializers and override their Meta classes to adjust the depth.

class ResourceNestedSerializer(ResourceSerializer):
    class Meta(ResourceSerializer.Meta):
        depth = 2

And in my view:

    if nested:
        serializer = ContainerNestedSerializer(containers, many=True)
    else:
        serializer = ContainerSerializer(containers, many=True)
    return Response(serializer.data)

Is there any way to adjust depth before calling serializer.data?

like image 370
Soviut Avatar asked May 25 '16 18:05

Soviut


People also ask

How do I change the foreign key value in Django REST framework?

As stated in the documentation, you will need to write your own create() and update() methods in your serializer to support writable nested data. You will also need to explicitly add the status field instead of using the depth argument otherwise I believe it won't be automatically added to validated_data .

How do you pass extra context data to Serializers in Django REST framework?

In function based views we can pass extra context to serializer with "context" parameter with a dictionary. To access the extra context data inside the serializer we can simply access it with "self. context". From example, to get "exclude_email_list" we just used code 'exclude_email_list = self.

What is nested serializer in Django REST framework?

DRF provides a Serializer class that gives you a powerful, generic way to control the output of your responses, as well as a ModelSerializer class that provides a useful shortcut for creating serializers that deal with model instances and querysets.

What is a nested serializer in Django?

Django rest framework: nested serializer. Django REST framework is a great package that gives you a head start on creating REST APIs, It makes developing the ideas into code faster and easier than ever. However, when you start customizing you’re app to fit your needs, things get trickier.

How to create REST API in Django?

For creating rest API in Django make sure you have installed Django and Django rest framework in your virtual environment. For installation, you can visit Django and Django rest framework websites. Once installation is done create your project and app. In my case, my Project name is DProject and my app name is API .

Can I use nested serializers in the rest framework?

Here I’m going to use nested serializers. The serializers in the REST framework work very similarly to Django’s Form and ModelForm classes.

What is Django-REST-framework-serializer-extensions?

The django-rest-framework-serializer-extensions package provides a collection of tools to DRY up your serializers, by allowing fields to be defined on a per-view/request basis. Fields can be whitelisted, blacklisted and child serializers can be optionally expanded.


1 Answers

Here is my code that incorporates including/excluding fields, as well as dynamically adjusting the depth. Adjust it to your taste. :)

class DynamicModelSerializer(serializers.ModelSerializer):
"""
A ModelSerializer that takes an additional `fields` argument that
controls which fields should be displayed, and takes in a "nested"
argument to return nested serializers
"""

def __init__(self, *args, **kwargs):
    fields = kwargs.pop("fields", None)
    exclude = kwargs.pop("exclude", None)
    nest = kwargs.pop("nest", None)

    if nest is not None:
        if nest == True:
            self.Meta.depth = 1

    super(DynamicModelSerializer, 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.keys())
        for field_name in existing - allowed:
            self.fields.pop(field_name)

    if exclude is not None:
        for field_name in exclude:
            self.fields.pop(field_name)
like image 184
Samir Avatar answered Sep 20 '22 08:09

Samir