0

我无法让它工作..我有以下序列化程序:

class OwnArbeitstagListSerializer(serializers.ModelSerializer):
    stundensumme = serializers.SerializerMethodField()
    class Meta:
        model = Arbeitstag
        ordering = ['-datum']
        fields = ('id', 'datum', 'in_abrechnung', 'stundensumme')
        depth=0

    def get_stundensumme(self, obj):
        return Stunden.objects.filter(arbeitstagid=obj.id).aggregate(Sum('stunden'))['stunden__sum']

.. 返回每天的工作时间总和(模型命名为“工作日”)。到目前为止有效。现在我想让 ModelViewset 返回工作日列表:

class OwnArbeitstagListViewSet(viewsets.ReadOnlyModelViewSet):
    filter_class = ArbeitstagListFilter
    filter_fields = ('datum',)
    filter_backends = (DjangoFilterBackend, filters.OrderingFilter, filters.SearchFilter,)
    ordering =["-datum"]
    serializer_class = OwnArbeitstagListSerializer
    def get_queryset(self):
        return Arbeitstag.objects.filter(userid=self.request.user.id)

你看,我正在按用户和日期(使用过滤器后端)过滤它。但是现在,我想要一个额外的字段,它给我 serializermethodfield“stundensumme”的总和。它的总和。它应该只计算显示对象的总和(应用了 datefilter)。

我遇到了麻烦,因为(我假设)Seriealizermethodfield 仅在序列化时才被计算,我想那为时已晚才能得到我的总和值。我试过这个,但它找不到序列化方法字段“stundensumme”来计算总和:

class CustomPageNumberPagination(PageNumberPagination):
    def get_paginated_response(self, data, summe):
        return Response(OrderedDict([
            ('count', self.page.paginator.count),
            ('next', self.get_next_link()),
            ('previous', self.get_previous_link()),
            ('summe', summe),
            ('results', data)
        ]))


class OwnArbeitstagListViewSet(viewsets.ReadOnlyModelViewSet):
    pagination_class = CustomPageNumberPagination
    filter_class = ArbeitstagListFilter
    filter_fields = ('datum',)
    filter_backends = (DjangoFilterBackend, filters.OrderingFilter, filters.SearchFilter,)
    ordering =["-datum"]
    serializer_class = OwnArbeitstagListSerializer
    def get_queryset(self):
        arbeitstag = Arbeitstag.objects.all().filter(userid=self.request.user.id)
        return arbeitstag
    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        self.summe = queryset.aggregate(Sum('stundensumme'))['stundensumme__sum']
        return super().list(request, *args, **kwargs)
    def get_paginated_response(self, data):
        return self.paginator.get_paginated_response(data, self.summe)
4

1 回答 1

0

如果您查看list()方法实现,您会发现:

    """
    List a queryset.
    """
    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())

        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

您的猜测是正确的,该stundensumme字段只会被序列化填充,因此您有两个选择:

  1. 使用anotate()并将其添加到您的定义中get_queryset(),因此每个对象都将具有该字段,并且您不需要在序列化程序中为该字段提供实现,您只需像您一样在 fields 属性中添加该字段

  2. get_paginated_response()你的总和,data因为它是序列化程序返回的列表,所以你可以轻松地操作它,例如:

    def get_summe(自我,数据):

    sum = 0
    for item in data:
        sum += item['stundensumme']
    return
    

并简单地使用它

def get_paginated_response(self, data):
    return Response(OrderedDict([
        ('count', self.page.paginator.count),
        ('next', self.get_next_link()),
        ('previous', self.get_previous_link()),
        ('summe', self.get_summe(data)),
        ('results', data)
    ]))

并且不要忘记删除您添加的额外代码,因为我们在这两种方式中都不需要它

于 2020-01-23T13:30:37.617 回答