如何获得Queryset中对象的计数



我有一个模型,其中包含如下字段:

class Vehicle(models.Model):
car_name = models.CharField(max_length=255)
car_color = models.CharField(max_length=255)

这个模型也有很多重复的值,我想显示不同的

查询集给出如下输出:

<QuerySet [{'car_name': 'Audi', 'car_color': 'Red'}, {car_name': 'BMW', 'car_color': 'white'}]>

[edit]我希望我的输出Queryset有另一个字段,它类似于输出的计数器。如果我从查询中得到两个对象,那么在queryset中也会发送一个名为ordinal_count的字段。

我正在寻找的输出例如:

<QuerySet [{'car_name': 'Audi', 'car_color': 'Red', 'ordinal_count': 1}, {car_name': 'BMW', 'car_color': 'white', 'ordinal_count': 2}, {car_name': 'Jaguar', 'car_color': 'olive green', 'ordinal_count': 3}]>

这是我写的查询:

op = (Vehicle.objects.annotate(ordinal_count=Count("car_name", distinct="car_name")).filter(car_color='white', list_display=True).values("car_name","car_color", "ordinal_count"))

这并没有给我想要的输入,而且也混淆了过滤器。我应该使用annotate吗?

然后我还写了另一个查询,但它无法运行:

NotImplementedError: annotate() + distinct(fields) is not implemented.

查询的方法是:

count = Vehicle.objects.filter(car_color='white', list_display=True).distinct(
"car_name").annotate(ordinal_count=Count("car_name")).values_list(
"car_name","car_color", "ordinal_count")

[编辑1]尝试了@trigo的解决方案,但它给了我一个输出(其中ordinal_count仍然为2)。我希望ordinal_count像一个计数器,用于查询集中的对象:

<QuerySet [{'car_name': 'Audi', 'car_color': 'Red', 'ordinal_count': 2}, {car_name': 'BMW', 'car_color': 'white', 'ordinal_count': 2}, {car_name': 'Jaguar', 'car_color': 'olive green', 'ordinal_count': 2}]>

(更新):

qs = (
Vehicle.objects.filter(car_color="white", list_display=True)
.distinct("car_name")
.annotate(ordinal_count=Window(expression=RowNumber(), partition_by=None))
.values("slug", "car_name", "car_color","ordinal_count")
).order_by('car_name')

这里唯一的问题是annotate在过滤之前工作。所以ordinal_count是混乱的。有没有办法先过滤一下?

edit3

假设总共有5个对象,我说我想要所有白色的汽车,有不同的car_name。

应用过滤器后的输出,似乎注释发生在过滤器之后,因为混乱的ordinal_count:

<QuerySet [{'car_name': 'Audi', 'car_color': 'white', 'ordinal_count': 3}, {car_name': 'BMW', 'car_color': 'white', 'ordinal_count': 2}, {car_name': 'Jaguar', 'car_color': 'white', 'ordinal_count': 5}]>

我没有一个完整的例子,但是在django模型中有一个窗口表达式(在里面你可以使用RowNumber()),可以帮助你:

from django.db.models.expressions import Window
from django.db.models.functions import RowNumber
query = Vehicle.objects.values(...).annotate(row_number=Window(expression=RowNumber()))

https://docs.djangoproject.com/en/4.1/ref/models/expressions/窗口函数

[假设]:这里的重复是指仅在属性"car_name"上。然而,如果你的意思是在"car_name"上复制,和";color"合并后,下面的查询集不能工作。如果是这样,请告诉我,我将提供其他解决方案。

下面的查询集将给出您想要的输出。

Vehicle.objects.filter().values("car_name").annotate(ordinal_count=Count("id")).order_by("car_name")

[注]:如果你的数据库是PostgreSQL,你可以使用distinct(),但是在其他数据库中,这是很容易实现的。

在复杂的查询中,您需要直接编写sql查询。

[编辑1]基本上,ordinal_count不是car_name出现的次数,而是计数器。对吧?根据您提供的预期输出,即

<QuerySet [{'car_name': 'Audi', 'car_color': 'Red', 'ordinal_count': 1}, {car_name': 'BMW', 'car_color': 'white', 'ordinal_count': 2}, {car_name': 'Jaguar', 'car_color': 'olive green', 'ordinal_count': 3}]>

根据上面的示例输出,通过ordinal_count您只表示计数器(即)数组的索引+ 1 ?根据你的例子,这是我能得出的唯一结论。对于这种情况,您可能根本不需要注释。

from django.db.models import Count, Window, F
Vehicle.objects.distinct('car_name').annotate(ordinal_count=Window(
expression=Count("id"),
partition_by=[F("car_name")]
)).values(
car_name,
car_color,
ordinal_count
).order_by('ordinal_count')

查询结果如下[{"car_name": "BMW", "car_color": "black", "ordinal_count": 5}...]

相关内容

  • 没有找到相关文章

最新更新