Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DRF: Retrieve outer input data from nested serializer validate method

I'm working with Django-Rest-Framework's serializers. I have two serializers one nested with the other.

class NestedSerializer(serializers.Serializer):
    value = AttributeValueField(required=True)
    name = serializers.CharField(required=True)

class OuterSerializer(serializers.Serializer):
    info = serializers.CharField()
    nested = NestedSerializer()

In order to validate the nested serializer's data I need to retrieve input data from the parent serializer, something like this:

class NestedSerializer(serializers.Serializer):
    ...
   def validate(self, data):
       # of course, it doesn't work, but thats the idea.
       info = self.parent.info
       # then validate the NestedSerializer with info.

I can't find any way to get access to those input data from the validate method. Any suggestions? Thanks for your help :).

like image 841
Brunoop Avatar asked Dec 26 '16 10:12

Brunoop


2 Answers

It might not be the best idea to do it this way, NestedSerializer should not be aware of the parent object. It would make your code difficult to maintain, also it would make NestedSerializer dependent on OuterSerializer.

Instead, define a validate(self, data) method in the OuterSerializer and run the mutual validation there.

like image 116
marxin Avatar answered Oct 05 '22 22:10

marxin


You can access initial_data on the parent serializer from the nested serializers validate() method. I've also added some code for using the parent fields run_validation() method, which would validate and return the internal value from to_internal_value(), which might be a better than dealing with the initial data.

class NestedSerializer(serializers.Serializer):

   def validate(self, data):
       # Retrieve the initial data, perhaps this is all you need.
       parent_initial_data = self.parent.initial_data
       info = parent_initial_data.get("info", None)

       # Get the corresponding field and use `run_validation` or `to_internal_value` if needed
       if info:
           info_field = self.parent.fields["info"]
           info = info_field.run_validation(info)
           # info = info_field.to_internal_value(info)  # If you don't want validation, but do want the internal value

       # Do your thing
       return data

like image 28
A. J. Parr Avatar answered Oct 05 '22 22:10

A. J. Parr