【问题标题】:Django: Serializing a list of multiple, chained modelsDjango:序列化多个链式模型的列表
【发布时间】:2017-01-19 14:31:21
【问题描述】:

给定两个不同的模型,具有相同的父基类。有什么方法可以使用 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)

【问题讨论】:

  • 我最好的猜测是,您的案例中的异常是从您未在此处共享的 BaseModelSerializer 序列化程序引发的
  • 啊,我明白了,我会在我测试过的序列化器中添加一些示例:)
  • 您将在堆栈跟踪中获得有关引发此错误的行的信息

标签: python django serialization django-rest-framework


【解决方案1】:

您可以根据模型定义将两个或多个序列化器组合在一起的序列化器:

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

这适用于任何模型,而不仅仅是一个班级的孩子。

【讨论】:

    【解决方案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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-11
      • 2013-11-27
      • 2011-08-26
      • 1970-01-01
      • 1970-01-01
      • 2014-11-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多