我有一个模型,其中包含如下字段:
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}...]