如何在DRF

时间:2016-01-18 15:21:52

标签: 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,
    )

serializer.py

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

如何在上面的模型上序列化JSON?

3 个答案:

答案 0 :(得分:3)

documentation中完整描述了这种情况。

因此,如果您想序列化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')

其中BookmarkNote是可能包含相关内容的对象。

如果您想序列化AddressBook,可以尝试这样做:

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

答案 1 :(得分:0)

我更喜欢使用第三方(rest-framework-generic-relations),如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')

答案 2 :(得分:0)

如果您的代码更加结构化,即每个应用程序都有其serializers.py,并且序列化程序的命名遵循约定(即[ModelName] Serializer),则可以使用动态导入来避免if ... elif ... else ...逻辑,从而避免松动耦合:

from django.utils.module_loading import import_string


class ContentObjectRelatedField(serializers.RelatedField):
    """
    A custom field to serialize generic relations
    """

    def to_representation(self, object):
        object_app = object._meta.app_label
        object_name = object._meta.object_name
        serializer_module_path = f'{object_app}.serializers.{object_name}Serializer'
        serializer_class = import_string(serializer_module_path)
        return serializer_class(object).data