粗略地说,我在ORM中具有以下架构:
class Page(models.Model):
title = models.CharField(max_length=255, null=False, blank=False)
@property
def content(self):
return [Video.objects.all()[0], Text.objects.all()[0], Video.objects.all()[1]]
并且我有以下几组类可支持序列化以获得详细视图:
class ContentSerializer(serializers.ListSerializer):
class Meta:
model = ???
fields = '???'
class PageDetailSerializer(serializers.ModelSerializer):
content = ContentSerializer(many=True)
class Meta:
model = Page
fields = ('title', 'content', )
所以我正在寻找一种序列化Page.content
属性的方法-即:
Video
,Audio
,Text
和其他模型的组合。因此,我需要以某种方式修补内置的序列化程序之一,以遍历列表并检查每个对象的类型。然后决定如何序列化每个。例如。我可以准备以下一种动态创建的ModelSerializer
:
obj_type = type(obj)
class ContentModelSerializer(serializers.ModelSerializer):
class Meta:
model = obj_type
fields = '__all__'
serialized_obj = ContentModelSerializer(obj)
我该如何实现?
答案 0 :(得分:1)
您可以通过覆盖to_representation
序列化器的Page
方法来简单地实现此目的。像这样:
class PageDetailSerializer(serializers.ModelSerializer):
class Meta:
model = Page
fields = ('title', 'content', )
def to_representation(self, instance):
ctx = super(PageDetailSerializer, self).to_representation(instance)
content = instance.content # property field of page, will return list of items
serialized_content = []
for c in content:
if type(c) == Video:
serialized_content.append({... serialized data of video type ..})
elif type(c) == ...
# other conditions here..
答案 1 :(得分:0)
在找到解决方案之前,我已经在Google上搜索了很多。 This article引用了SerializerMethodField
,可让您为字段添加自定义处理程序。对我有用的最终解决方案是:
class PageDetailSerializer(serializers.ModelSerializer):
_cache_serializers = {}
content = serializers.SerializerMethodField()
class Meta:
model = Page
fields = ('title', 'content', )
def _get_content_item_serializer(self, content_item_type):
if content_item_type not in self._cache_serializers:
class ContentItemSerializer(serializers.ModelSerializer):
class Meta:
model = content_item_type
exclude = ('id', 'page', )
self._cache_serializers[content_item_type] = ContentItemSerializer
return self._cache_serializers[content_item_type]
def get_content(self, page):
return [
self._get_content_item_serializer(type(content_item))(content_item).data for content_item in page.content
]