Django Rest框架化关系

时间:2016-08-11 10:50:18

标签: django django-rest-framework

如何序列化相关模型中的字段。

我有一个模特:

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

串行:

class ReportSerializer(ModelSerializer):

    class Meta:
        model = Report
        depth = 1

我需要在get_queryset()中的'queryset'中获取所有字段 但是我收到了一个错误:

  尝试获取字段imp的值时,

获得了AttributeError   序列化器ReportSerializer。序列化程序字段可能已命名   错误且不匹配tuple上的任何属性或键   实例。原始异常文本是:'tuple'对象没有属性   '小鬼'。

但是如果我在get_queryset()中返回只是Report.objects.filter(month = month).all()我将获得所有对象和相关对象的所有字段,没有imp的聚合而不是分组。

所以问题是如何在queryset中设置序列化器返回结构?

2 个答案:

答案 0 :(得分:1)

get_queryset方法需要返回一个查询集,但由于values_list而返回一个元组。删除它以返回查询集或使用更通用的视图,如APIView

答案 1 :(得分:0)

我找到了一种方法。

当我使用.values_list()时,它返回列表对象而不是queryset对象。因此,对于序列化程序,请了解列表中的内容,我在序列化程序中定义了所有字段。在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)