如何在DRF中序列化通用外键

Nar*_*esh 5 python django serialization django-rest-framework

我有带有通用外键的模型,我想序列化该模型。

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,
    )
Run Code Online (Sandbox Code Playgroud)

serializer.py

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

如何在上述模型上序列化JSON?

小智 8

我更喜欢使用此第三方(rest-framework-generic-relations),如文档中所述

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')
Run Code Online (Sandbox Code Playgroud)


Dev*_*nky 6

文档中对此情况进行了详细描述。

因此,如果您要序列化AddressType,则需要实现以下内容:

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')
Run Code Online (Sandbox Code Playgroud)

其中BookmarkNote是可能具有关联内容的对象。

如果要序列化AddressBook,可以尝试执行以下操作:

class AddressBookSerializer(serializers.ModelSerializer):
    address_object_type = ContentObjectRelatedField()
    class Meta:
        model = AddressBook
        fields = ('id','uuid','address_tag','address_object_type','address1','address2')
Run Code Online (Sandbox Code Playgroud)