2016-08-11 4 views
1

関連モデルのフィールドを直列化する方法。Django Restフレームワークの関係を整理する

class Order(models.Model): 
    order_id = models.BigIntegerField(verbose_name='Order ID', unique=True) 
    order_name = models.CharField(verbose_name='Order name', max_length=255) 
    order_type = models.IntegerField(verbose_name='Campaign type') 

class Types(models.Model): 
    delimiter = models.CharField(verbose_name='Delimiter', max_length=255) 
    status = models.BooleanField(verbose_name='Status', default=True) 
    title = models.CharField(verbose_name='Title', max_length=255) 

class User(models.Model): 
    name = models.CharField(verbose_name='User name', max_length=200, unique=True) 

class Report(models.Model): 
    order = models.ForeignKey(Order, to_field='order_id', verbose_name='Order ID') 
    user = models.ForeignKey(User, verbose_name='User ID') 
    ad_type = models.ForeignKey(Types, verbose_name='Type') 
    imp = models.IntegerField(verbose_name='Total imp') 
    month = models.DateField(verbose_name='Month', default=datetime.datetime.today) 

ビュー:

class ReportLisAPIView(ListAPIView): 
    serializer_class = ReportSerializer 

    def get_queryset(self): 
     month = parse_date(self.kwargs['month']) - relativedelta(day=1) 

     queryset = (
      Report.objects.filter(month=month) 
      .values_list(
       'user', 'user__name', 'order__order_id', 
       'order__order_name', 'order__order_type' 
      ).all().annotate(Sum('imp')) 
     ) 
     return queryset 

シリアライザ:私はget_querysetの 'クエリセット' のようにすべてのフィールドを取得する必要があり

class ReportSerializer(ModelSerializer): 

    class Meta: 
     model = Report 
     depth = 1 

()

は私がモデルですエラーが発生しました:

Got AttributeError when attempting to get a value for field imp on
serializer ReportSerializer . The serializer field might be named incorrectly and not match any attribute or key on the tuple instance. Original exception text was: 'tuple' object has no attribute 'imp'.

しかし、私がget_queryset()に戻った場合は、Report.objects.filter(月=月).all()だけで、すべてのフィールドと関連オブジェクトを取得します。

それでは、クエリーセットで設定したシリアライザのリターン構造をどうやって作るのですか?

答えて

1

get_querysetメソッドはクエリセットを返す必要がありますが、values_listのタプルビーコンが返されています。クエリーセットを返すか、APIViewのようなより一般的なビューを表示するにはドロップします。

0

私はそれを行う方法を見つけました。

私は.values_list()を使用するので、クエリーセットオブジェクトの代わりにリストオブジェクトを返します。したがってシリアライザでは、シリアライザのすべてのフィールドを定義したリストの中身を理解しています。そしてto_representation()の中で、私はそれがそうであるように辞書を返します。

シリアライザ:

class ReportSerializer(serializers.ModelSerializer): 
    user = serializers.IntegerField() 
    user_name = serializers.CharField() 
    order_id = serializers.IntegerField() 
    order_name = serializers.CharField() 
    order_type = serializers.IntegerField() 
    imp = serializers.IntegerField() 

class Meta: 
    model = Report 
    fields = [ 
     'user', 'user_name', 'order_id', 'order_name', 
     'order_type', 'imp' 
    ] 
    depth = 1 

def to_representation(self, instance): 
    Reports = namedtuple('Reports', [ 
     'user', 
     'user_name', 
     'order_id', 
     'order_name', 
     'order_type', 
     'imp', 
    ]) 
    return super(ReportSerializer, self).to_representation(
     Reports(*instance)._asdict() 
    ) 

ビュー:?

class ReportLisAPIView(ListAPIView): 
    serializer_class = ReportSerializer 

    def get_queryset(self): 
     month = parse_date(self.kwargs['month']) - relativedelta(day=1) 

     queryset = (
      Report.objects.filter(month=month) 
      .values_list(
       'user', 'user__name', 'order__order_id', 
       'order__order_name', 'order__order_type' 
      ).all().annotate(Sum('imp')) 
     ) 
     return queryset 

    def list(self, *args, **kwargs): 
     queryset = self.get_queryset() 
     serializer = self.serializer_class(queryset, many=True) 
     # actualy that's it! part of which is below can be pass and just 
     # return Response(serializer.data) 

     result = { 
      'month': parse_date(self.kwargs['month']).strftime('%Y-%m'), 
      'reports': [] 
     } 

     inflcr = {} 
     for item in serializer.data: 
      inflcr.setdefault(item['user'], { 
       'id': item['user'], 
       'name': item['user_name'], 
       'campaigns': [] 
      }) 

      orders = { 
       'id': item['order_id'], 
       'name': item['order_name'], 
       'type': item['order_type'], 
       'impressions': item['imp'], 
      } 

      inflcr[item['user']]['campaigns'].append(orders) 
     result['reports'] = inflcr.values() 

    return Response(result) 
+0

説明... – marcusshep

+0

申し訳ありません。私は私の答えに説明を追加しました。 – user2160537

関連する問題