【问题标题】:How to Serialize generic foreign key In DRF如何在 DRF 中序列化通用外键
【发布时间】:2016-04-23 19:54:18
【问题描述】:

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

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?

【问题讨论】:

    标签: python django serialization django-rest-framework


    【解决方案1】:

    这个案例在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')
    

    【讨论】:

    • 我也做过同样的事情,但无法成功...不胜感激....如果您能在代码方面提供帮助...
    • 我收到错误:“TypeError: is not JSON serializable”
    • 所有代码都在那里,除了视图......在视图中我正在调用序列化程序......这里的内容类型将是用户对象......
    【解决方案2】:

    我更喜欢使用此第三方 (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')
    

    【讨论】:

      【解决方案3】:

      如果您的代码更加结构化,即每个应用程序都有其 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
      

      【讨论】:

        猜你喜欢
        • 2019-07-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-06-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多