Skip to content

Instantly share code, notes, and snippets.

@zealws
Last active August 29, 2015 14:11
Show Gist options
  • Save zealws/c71056b6051ac890e776 to your computer and use it in GitHub Desktop.
Save zealws/c71056b6051ac890e776 to your computer and use it in GitHub Desktop.
rest-framework 3.0 top-down serialization

Old serializers.py:

class ASerializer(serializers.Serializer):
    f1 = serializers.IntegerField(default=0)
    f2 = serializers.IntegerField(default=1)
    
    def restore_object(self, attrs, instance=None):
        return A(**attrs)

class BSerializer(serializers.Serializer):
    f1 = serializers.IntegerField(default=2)
    f2 = serializers.IntegerField(default=3)
    
    def restore_object(self, attrs, instance=None):
        return B(**attrs)

class CompositeSerializer(serializers.Serializer):
    a = ASerializer(required=False)
    b = ASerializer(required=False)
    
    def restore_object(self, attrs, instance=None):
        print 'CompositeSerializer attributes:', attrs
        return CompositeSerializer(**attrs)

Output of the old code using django-rest-framework 2.4:

CompositeSerializer attributes: {"a": A(17, 1), "b": B(2, 19)}

By the time CompositeSerializer's restore_object is called, the subobjects (A and B) have already been serialized.

New serializers.py:

class ASerializer(serializers.Serializer):
    f1 = serializers.IntegerField(default=0)
    f2 = serializers.IntegerField(default=1)
    
    def create(self, attrs):
        return A(**attrs)

class BSerializer(serializers.Serializer):
    f1 = serializers.IntegerField(default=2)
    f2 = serializers.IntegerField(default=3)
    
    def create(self, attrs):
        return B(**attrs)

class CompositeSerializer(serializers.Serializer):
    a = ASerializer(required=False)
    b = ASerializer(required=False)
    
    def create(self, attrs):
        print 'CompositeSerializer attributes:', attrs
        as = ASerializer(data=attrs["a"])
        bs = BSerializer(data=attrs["b"])
        if !as.is_valid() or !bs.is_valid():
            return None
        a = as.save()
        b = bs.save()
        return Composite(a=a, b=b)

Output of the new code using django-rest-framework 3.x:

CompositeSerializer attributes: OrderedDict([('a', OrderedDict([('f1', 17)])), ('b', OrderedDict([('f2', 19)]))])

Now, A and B have not yet been serialized, so if Composite wants the data , it needs to deserialize them itself.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment