2017-01-19 66 views
2

同じ親の基底クラスを持つ2つの異なるモデルが与えられています。両方の子モデルのインスタンスを含む連鎖リストを直列化するには、Django Rest Frameworkシリアライザまたはserpyを使用する方法はありますか?Django:連鎖した複数のモデルのリストをシリアライズ

考えると、いくつかの例モデル:

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

あなたがここで共有していない 'BaseModelSerializer'シリアライザから例外が発生しました –

+0

ああ、私がテストしたシリアライザにいくつかの例を追加します:) –

+0

あなたはこのエラーを引き起こす行に関するスタックトレースの情報 –

答えて

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 

これは、1つのクラスの子どもだけでなく、どのモデルでも機能します。

2

をあなたの例外から、私はBaseModelSerializerに問題があることを想定両方のモデルから。私は、あなたがより良い各モデルのための2つの別々のシリアライザを書き、その後、一般的なフィールドによってそれらからの出力をソート思う:

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) 
関連する問題