给出两个不同的模型,具有相同的父基类。有没有办法,使用Django Rest Framework Serializers或serpy来序列化包含两个子模型实例的链式列表?
给出一些示例模型:
class BaseModel(models.Model):
created_at = models.DateField()
class Meta:
abstract = True
class ChildModel1(BaseModel):
field_one = models.TextField()
class ChildModel2(BaseModel):
field_two = models.TextField()
示例视图:
def get(self, request):
q1 = ChildModel1.objects.all()
q2 = ChildModel2.objects.all()
chained_list = sorted(
chain(q1, q2),
key=attrgetter('created_at'))
serializer = BaseModelSerializer(chained_list, many=True)
链接模型的方法取自this问题的答案。
根据我目前的尝试,我得到一个非常明显的错误,例如:
AttributeError: 'ChildModel1' object has no attribute 'field_two'
我知道将两个模型与一些不同的字段混合起来并不是最好的做法,但在我的情况下,我认为这是必要的。
我测试的一些串行器示例:
第一个例子:
class BaseModelSerializer(serializers.ModelSerializer):
class Meta:
model = BaseModel
第二个例子:
class BaseModelSerializer(serpy.Serializer):
created_at = serpy.StrField()
field_one = serpy.StrField(required=False)
field_two = serpy.StrField(required=False)
答案 0 :(得分:2)
从您的例外情况来看,我认为BaseModelSerializer
存在问题,因为它同时包含两个模型的两个字段。我认为你最好为每个模型编写两个单独的序列化器,然后按公共字段对它们的输出进行排序:
class ChildModel1Serializer(serializers.ModelSerializer):
class Meta:
model = ChildModel1
fields = ('created_at', 'field_one')
class ChildModel2Serializer(serializers.ModelSerializer):
class Meta:
model = ChildModel2
fields = ('created_at', 'field_two')
views.py:
def get(self, request):
q1 = ChildModel1.objects.all()
q2 = ChildModel2.objects.all()
# evaluate querysets and get a serializeble output in a list
serializer1 = ChildModel1Serializer(q1, many=True).data
serializer2 = ChildModel2Serializer(q2, many=True).data
# concatenate two lists of dicts and sort it by 'created_at' key
chained_list = sorted(serializer1 + serializer2, key=lambda x: x.get('created_at'))
return Response(chained_list)
答案 1 :(得分:2)
您可以定义序列化程序,它将根据模型将两个或多个序列化程序组合在一起:
class Model1Serializer(serializers.Serializer):
...
class Model2Serializer(serializers.Serializer):
...
class SummarySerializer(serializers.Serializer):
""" Serializer that renders each instance with its own specific serializer """
@classmethod
def get_serializer(cls, model):
if model == Model1:
return Model1Serializer
elif model == Model2:
return Model2Serializer
def to_representation(self, instance):
serializer = self.get_serializer(instance.__class__)
return serializer(instance, context=self.context).data
这适用于任何模型,不仅适用于一个类的孩子。