Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing serializer instances in nested serializer's field

Is there a way inside of a field in a nested serializer, to access the parent serializer's instance. Specifically the instance being accessed in a list view especially where the top most serializer may have multiple instances. I would like to pass this as context, but the context is passed by the view.

When inside the field's to_representation, on a list for instance, I can access the list of instances on the parent in list view, but i'm not sure which one is the current instance being processed.

like image 682
Moylin Avatar asked Aug 13 '15 16:08

Moylin


1 Answers

The question is a bit too broad so Ill give a generic answer.

Any field in DRF (including serializers since they subclass from fields) can access the parent serializer via self.parent. In addition you can also access the root serializer itself (the serializer being instantiated in the views) via self.root.

However from what I get gather in your question, you are trying to access some state from the parent serializer while in the middle of executing to_representation. Doing that is slippery slope since in DRF both serialization and validation are stateless processes. In other words, only root serializer can have state (store state on self) but that should not happen in child serializers. If you need to access state, the best way is to explicitly pass the state around between serializers. For example:

class ChildSerializer(Serializer):
    def to_representation(self, instance):
        foo = instance.foo  # comes from parent serializer
        ...

class RootSerializer(Serializer):
    child = ChildSerializer()
    def to_representation(self, instance):
        instance.foo = 'foo'  # parent is setting state
        ...

You also mentioned that you are using lists. That will involve ListSerializers so if you need to pass state with in there and therefore create a custom ListSerializer:

class RootListSerializer(ListSerializer):
    def to_representation(self, instance):
        for i in instance:
            i.foo = 'foo'
        ...

class RootSerializer(Serializer):
    class Meta(object):
        list_serializer_class = RootListSerializer
like image 196
miki725 Avatar answered Oct 18 '22 05:10

miki725