12

问题

我有一个具有以下标准通用外键字段的模型:

content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
event_object = generic.GenericForeignKey('content_type', 'object_id')

根据 REST framework 的文档,我可以执行以下操作来正确序列化:

class WhateverSerializer(serializers.ModelSerializer):
    event_object = serializers.RelatedField(source='event_object')

这很好用,但是在其他两种相关情况下,我无法正常工作:

  1. 我想用HyperlinkedRelatedField. 此字段需要 view_name 参数,我无法声明,因为视图名称因相关模型而异。我通过使用SerializerMethodField,在运行时实例化 aHyperlinkedIdentityField并返回它的field_to_native方法来解决这个问题(见下面的片段)。这感觉不是很优雅。
  2. 我想通过说将相关对象直接嵌套在序列化中event_object = SoAndSoSerializer(source='event_object')。我能看到的唯一解决方案是遍历*Serializer我定义的每一个并检查哪个具有正确的模型,然后使用它。同样,这感觉不是很优雅。

问题

HyperlinkRelatedField 是否意味着跨通用关系工作?我只是在犯错吗?是否有明显的解决方案来选择*Serializer我缺少的权利?

代码片段

上面第 1 点中提到的不优雅的解决方案:

class WhateverSerializer(DefaultSerializer):

    event_object_url = serializers.SerializerMethodField('get_related_object_url')
    # ...

    def get_related_object_url(self, obj):
        obj = obj.event_object
        default_view_name = '%(model_name)s-detail'
        format_kwargs = {
            'app_label': obj._meta.app_label,
            'model_name': obj._meta.object_name.lower()
        }
        view_name = default_view_name % format_kwargs
        s = serializers.HyperlinkedIdentityField(source=obj, view_name=view_name)
        s.initialize(self, None)
        return s.field_to_native(obj, None)
4

1 回答 1

8

你说得对,REST 框架不支持这些用例,而且对我来说,如果支持的话,设计会是什么样子并不明显。您可能需要一个隐式注册表模型-> 视图(对于超链接的情况)和模型-> 序列化程序(对于嵌套的情况),我认为我不会非常热衷于此。

做你需要的最简单的方法可能是子类化ManyRelatedField并创建一个自定义字段类型,重写to_native(self, obj)以完全按照你想要的方式序列化集合中的每个对象。

于 2013-01-22T08:48:48.463 回答