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

序列化器:

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?

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

我找到了一个方法。

当我使用。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)