django-filter-在过滤数据中添加聚合

时间:2018-08-22 19:33:25

标签: django django-filter

我需要添加一些过滤后的数据,并且我正在使用汇总来执行此操作:

class MunicipioList(generics.ListAPIView):
    queryset = Municipio.objects.filter().order_by('-id')
    extra_counts = queryset.aggregate(
        cidades=Count('pk', filter=Q(cidade__isnull=False)),
        estados=Count('pk', filter=Q(cidade__isnull=True)),
        estados_aderidos=Count('pk', filter=(Q(usuario__estado_processo=6) & Q(cidade__isnull=True))),
        municipios_aderidos=Count('pk', filter=(Q(usuario__estado_processo=6) & Q(cidade__isnull=False))),
    )
    serializer_class = MunicipioSerializer
    metadata_class = MunicipioMetadata

    filter_backends = (DjangoFilterBackend, filters.OrderingFilter,)
    filter_class = MunicipioFilter
    ordering_fields = ('cidade__nome_municipio', 'estado__nome_uf')

    def list(self, request):
        response = super(MunicipioList, self).list(self, request)
        response.data['cidades'] = self.extra_counts['cidades']
        response.data['estados'] = self.extra_counts['estados']
        response.data['estados_aderidos'] = self.extra_counts['estados_aderidos']
        response.data['municipios_aderidos'] = self.extra_counts['municipios_aderidos']
        return response

但是计数是错误的,导致查询集未过滤,因此它始终基于所有对象。我正在使用django-filter。有人可以帮忙吗?

1 个答案:

答案 0 :(得分:0)

您应该对过滤后的查询集进行汇总:

class MunicipioList(generics.ListAPIView):
    queryset = Municipio.objects.filter().order_by('-id')

    serializer_class = MunicipioSerializer
    metadata_class = MunicipioMetadata

    filter_backends = (DjangoFilterBackend, filters.OrderingFilter,)
    filter_class = MunicipioFilter
    ordering_fields = ('cidade__nome_municipio', 'estado__nome_uf')


    def get_extra_counts(self): ## in this function first get the filtered queryset then do the aggregate and return it
        queryset = self.filter_queryset(self.get_queryset())
        return queryset.aggregate(
            cidades=Count('pk', filter=Q(cidade__isnull=False)),
            estados=Count('pk', filter=Q(cidade__isnull=True)),
            estados_aderidos=Count('pk', filter=(Q(usuario__estado_processo=6) & Q(cidade__isnull=True))),
            municipios_aderidos=Count('pk', filter=(Q(usuario__estado_processo=6) & Q(cidade__isnull=False))),
        )



    def list(self, request):
        response = super(MunicipioList, self).list(self, request)
        extra_counts = self.get_extra_counts() ## get the extra_counts on the filtered queryset
        response.data['cidades'] = extra_counts['cidades']
        response.data['estados'] = extra_counts['estados']
        response.data['estados_aderidos'] = extra_counts['estados_aderidos']
        response.data['municipios_aderidos'] = extra_counts['municipios_aderidos']
        return response