Django 1.11订单结果问题-注释计数返回错误值

时间:2018-10-27 14:11:54

标签: python django

我正在使用Django 1.11:

  • 我有一个模型定义,用于计算外键属性上的假值数量,如下所示:

型号:

class Model(models.Model):
    .
    . 
    . 

    def count_total(self):
        return self.anothermodel_set.filter(val=False).count()

查看:

class ModelViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = Model.objects.all()
    serializer_class = ModelSerializerClass
    permissions = AuthenticatedReadOnly
    pagination_class = StandardResultsSetPagination

    def list(self, request):
        queryset = Model.objects.all()

        # Attempt 1: returns wrong count
        queryset = queryset.annotate(a_count=Count(Case(When(anothermodel__val=False, then=1), default=0, output_field=IntegerField())))

        # Attempt 2: returns wrong count, same as attempt 1
        queryset = queryset.annotate(b_count=Count(Q(anothermodel__val=False)))

        # ideally I want to do 
        queryset = queryset.order_by('count_total')

当我通过count_total进行订购时,我会给出

  

/ api / endpoint /中的FieldError   无法将关键字“ count_total”解析为字段。

序列化器

在我的序列化程序中,我已经修改了to_represantation定义以进行调试:

def to_representation(self, instance):
    return {'id': instance.pk, 'a_count': instance.a_count, 'b_count' : instance.b_count, 'correct_count': instance.count_total()}

否则在我的序列化程序中,我有:

class Meta:
    model = Model
    fields = ('id', 'title', 'bunch-of-other-stuff', 'count_total')

instance.count_total()返回正确的结果,但是我不能在视图中简单地将其用作queryset.order_by('count_total')来排序没有注释的结果。

有什么主意吗?

2 个答案:

答案 0 :(得分:2)

我不确定这是否是您的问题,但是模型定义似乎未使用,因为您没有返回值,只是进行了计算。应该是:

def count_total(self):
        return self.anothermodel_set.filter(val=False).count()

对于为什么在模型和视图中都要进行计算,我也感到困惑。既可以使用模型定义,也可以注释查询集,但是您不必同时使用两者。如果您使用模型定义路线,则视图应如下所示:

class ModelViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = Model.objects.all()
    serializer_class = ModelSerializer
    permissions = AuthenticatedReadOnly
    pagination_class = StandardResultsSetPagination

    def list(self, request):

        queryset = self.queryset.order_by('count_total')
        serializer = self.get_serializer(queryset, many=True)

        return Response(serializer.data)

如果使用模型定义,则需要在序列化程序中设置类似read_only属性的内容:

count_total = serializers.ReadOnlyField(allow_null=True)

class Meta:
    model = Model
    fields = ('id', 'title', 'bunch-of-other-stuff', 'count_total')

如果仍然遇到“无法将总数解析为字段”错误,请在运行序列化程序之前将打印语句放入视图集中:

print(str(queryset))

问题可能出在您如何过滤模型定义上。

答案 1 :(得分:0)

将近 3 年后;但它可能会为遇到此问题的其他人节省一些时间。

# Attempt 2: returns wrong count, same as attempt 1
queryset = queryset.annotate(b_count=Count(Q(anothermodel__val=False)))

这个问题与多个注释组合在一起的事实有关。上面遗漏的部分是指定我们只想计算 distinct=True 值以避免 the perlvar page of the perl manual。像这样:

# Success
queryset = queryset.annotate(
    b_count=Count(
        Q(anothermodel__val=False), distinct=True
    )
)