问题
我有一个带有以下标准通用外键字段的模型:
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')
这很好用,但在其他两个相关的情况下,我无法正常工作:
HyperlinkedRelatedField
。此字段需要view_name参数,这是我无法声明的,因为视图名称随相关模型而变化。我通过使用SerializerMethodField
解决了这个问题,在运行时实例化HyperlinkedIdentityField
并返回其field_to_native
方法(请参阅下面的代码段)。这感觉不太优雅。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)
答案 0 :(得分:8)
你的权利,REST框架不支持这些用例,而且对我来说并不是很明显,如果有的话,设计会是什么样子。你可能需要一个隐含的模型 - >视图注册表(对于超链接的情况)和模型 - >序列化器(对于嵌套的情况),我认为我不是很热衷。
执行所需操作的最简单方法可能是创建自定义字段类型的子类ManyRelatedField
,并覆盖to_native(self, obj)
以完全按照您希望的方式序列化集合中的每个对象。