【问题标题】:Django Rest Framework serilize relationsDjango Rest Framework 序列化程序关系
【发布时间】:2016-12-18 01:42:59
【问题描述】:

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

我有一个模型:

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 上的任何属性或键 实例。原始异常文本是:“元组”对象没有属性 '小鬼'。

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

所以问题是如何使序列化程序返回在查询集中设置的结构?

【问题讨论】:

    标签: django django-rest-framework


    【解决方案1】:

    我找到了一种方法。

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

    【讨论】:

    • 对不起。我在答案中添加了描述。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2015-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-19
      • 2014-11-03
      • 1970-01-01
      相关资源
      最近更新 更多