Django REST框架和通用关系

时间:2013-01-21 23:01:46

标签: django django-rest-framework

问题

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

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

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

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

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

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

    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)
    

1 个答案:

答案 0 :(得分:8)

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

执行所需操作的最简单方法可能是创建自定义字段类型的子类ManyRelatedField,并覆盖to_native(self, obj)以完全按照您希望的方式序列化集合中的每个对象。