代码之家  ›  专栏  ›  技术社区  ›  ElasticPanda

按年月嵌套序列化程序

  •  1
  • ElasticPanda  · 技术社区  · 10 月前
    class Transactions(models.Model):
        id = models.CharField(max_length=100, primary_key=True)
        owner = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
        date = models.DateField()
        watch = models.CharField(max_length=100)
        purchase_price = models.IntegerField()
        sale_price = models.IntegerField()
    

    我的交易模型有一个日期字段、购买价格和sale_price。

    @api_view(['GET'])
    @permission_classes([IsAuthenticatedOrReadOnly])
    def profit_chart(request):
        current_year = datetime.now().year
        queryset = Transactions.objects.filter(date__year=current_year).values(month=ExtractMonth('date'),
                                                                               year=ExtractYear('date')).annotate(
            profit=Sum(F('sale_price')) - Sum(F('purchase_price'))).order_by('month')
        serializer = ProfitChartSerializer(queryset, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)
    

    我的视图按当前年份和月份对交易进行排序,然后计算当月的利润。

    class ProfitChartSerializer(serializers.ModelSerializer):
        year = serializers.IntegerField()
        month = serializers.IntegerField()
        profit = serializers.IntegerField()
    
        class Meta:
            model = Transactions
            fields = ['year', 'month', 'profit']
    

    我从DRF得到的回应如下。

    [
        {
            "year": 2024,
            "month": 8,
            "profit": 5000
        }
    ]
    

    我试图弄清楚的问题是,我如何操纵上述反应,使其看起来像下面这样。

    [
        year:  2024
        data: {
            month: 8
            profit: 5000
        }
    ]
    
    1 回复  |  直到 10 月前
        1
  •  0
  •   willeM_ Van Onsem    10 月前

    我认为这没有多大意义。事实上,你按年份过滤:

    queryset = Transactions.objects.filter(date__year=current_year)

    因此,所有返回记录的年份都是相同的。

    但是,您可以在这里使用以下命令自定义序列化程序:

    class PartialChartSerializer(serializers.ModelSerializer):
        month = serializers.IntegerSerializer()
        profit = serializers.IntegerField()
    
        class Meta:
            model = Transactions
            fields = ['month', 'profit']
    
    
    class ProfitChartSerializer(serializers.Serializer):
        year = serializers.IntegerField()
        data = PartialChartSerializer(many=True)

    并将项目馈送到序列化器,如下所示:

    from itertools import groupby
    from operator import itemgetter
    
    
    @api_view(['GET'])
    @permission_classes([IsAuthenticatedOrReadOnly])
    def profit_chart(request):
        queryset = (
            Transactions.objects.values(
                month=ExtractMonth('date'), year=ExtractYear('date')
            )
            .annotate(profit=Sum(F('sale_price')) - Sum(F('purchase_price')))
            .order_by('month')
        )
        serializer = ProfitChartSerializer(
            [
                {'year': k, 'data': list(vs)}
                for k, vs in groupby(queryset, itemgetter('year'))
            ],
            many=True,
        )
        return Response(serializer.data, status=status.HTTP_200_OK)

    注: :通常给Django模型一个 singular name [django-antipatterns] ,所以 Transaction 而不是 Transactions .