Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Serialize generic foreign key In DRF

I have model with generic foreign key and I want to serialize that model.

model.py:

class AddressType(models.Model):
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type','object_id')

    def __unicode__(self):
        return u'%s' % str(self.content_type)

class AddressBook(TimeStampedModel):
    class Meta:
        db_table = 'address_book'

    uuid = UUIDField(auto=True)
    address_tag = models.CharField(null=True, blank=True, max_length=20)

    # should be a generic foreign key
    address_object_type = GenericRelation(AddressType)
    address1 = models.CharField(
        verbose_name='Address1',
        max_length=200,
    )
    address2 = models.CharField(
        verbose_name='Address2',
        max_length=200,
    )

serializer.py:

class AddressBookSerializer(serializers.ModelSerializer):
    class Meta:
        model = AddressBook
        fields = ('id','uuid','address_tag','address_object_type','address1','address2')

How can I serialize JSON on above model?

like image 899
Naresh Avatar asked Jan 18 '16 15:01

Naresh


Video Answer


2 Answers

This case is perfectly described in the documentation.

So if you want to serialize AddressType you will need to implement something like this:

class ContentObjectRelatedField(serializers.RelatedField):
    """
    A custom field to use for the `content_object` generic relationship.
    """

    def to_representation(self, value):
        """
        Serialize tagged objects to a simple textual representation.
        """
        if isinstance(value, Bookmark):
            return 'Bookmark: ' + value.url
        elif isinstance(value, Note):
            return 'Note: ' + value.text
        raise Exception('Unexpected type of tagged object')

Where Bookmark and Note are objects which may be have associated contents.

If you want to serialize AddressBook you can try doing something like this:

class AddressBookSerializer(serializers.ModelSerializer):
    address_object_type = ContentObjectRelatedField()
    class Meta:
        model = AddressBook
        fields = ('id','uuid','address_tag','address_object_type','address1','address2')
like image 155
DevilPinky Avatar answered Nov 12 '22 19:11

DevilPinky


I'd prefer use this third party (rest-framework-generic-relations) as also described in documentation.

from generic_relations.relations import GenericRelatedField

class TagSerializer(serializers.ModelSerializer):
    """
    A `TaggedItem` serializer with a `GenericRelatedField` mapping all possible
    models to their respective serializers.
    """
    tagged_object = GenericRelatedField({
        Bookmark: BookmarkSerializer(),
        Note: NoteSerializer()
    })

    class Meta:
        model = TaggedItem
        fields = ('tag_name', 'tagged_object')
like image 44
msmaromi Avatar answered Nov 12 '22 20:11

msmaromi