【问题标题】:Django taggit aggregation query to return count per tagDjango taggit 聚合查询返回每个标签的计数
【发布时间】:2021-08-03 04:11:26
【问题描述】:

我正在使用 Django 3.2 和 django-taggit 1.4

我有一个这样的模型:

class Meal(models.Model):
    # some fields
    is_cooked = models.Boolean()
    tags = TaggitManager()

我正在尝试生成一个以标签名称和标签出现次数为键的字典 - 但仅适用于将 is_cooked 标志设置为 True 的餐点。

我尝试了以下方法:

pks = list(Meal.objects.filter(is_cooked=True))
ct = ContentType.objects.get_for_model(Meal)
b=TaggedItem.objects.filter(content_type=ct, object_id__in=pks).annotate(num_times=Count('tag__name'))

这并没有返回预期的结果(而且我预计由于查找次数过多,它可能会多次访问数据库 - 但我不想因过早的优化问题而分心。

我做错了什么,如何获得每个标签的标签数量?

[[编辑]]

以下是运行上述查询的结果:

<QuerySet [<TaggedItem: Meal One tagged with rice>, <TaggedItem: Meal Two tagged with chips>, <TaggedItem: Meal Three tagged with curry>, <TaggedItem: Meal Four tagged with royalty>, <TaggedItem: Meal Five tagged with rice>, <TaggedItem: Meal Six tagged with chips>]>


>>> b[0].num_times
1

【问题讨论】:

  • 嗨,什么是意外输出?
  • @jspcal:请参阅编辑

标签: python django django-queryset django-taggit


【解决方案1】:

您可以使用以下方法过滤注释:

from django.db.models import Count, Q
from taggit.models import Tag

Tag.objects.annotate(
    nmeal=Count('meal', filter=Q(meal__is_cooked=True))
)

来自 thsi 查询集的 Tag 对象将具有一个额外的属性 .nmeals,其中包含餐的数量。

如果您只想检索至少有一个相关熟食的Tag 对象,您可以使用:

from django.db.models import Count, Q
from taggit.models import Tag

Tag.objects.filter(
    meal__is_cooked=True
).annotate(
    nmeal=Count('meal')
)

【讨论】:

  • Tag 对象怎么知道'meal' 是什么??? (这是什么魔法):D
  • @HomunculusReticulli:TaggableManager 基本上是一种ManyToManyField,因此我们可以查询到具有TaggableManager 的某个模型。
  • 我猜它在幕后做了一种'related_name'。这简直就是魔法!模型名称和 Tag 对象期望的名称之间的映射是什么?例如,它会像 MySuperDoopaClass 这样的类的名称'mangle'吗?我需要将什么传递给 Tag 对象才能使查询仍然有效?
  • @HomunculusReticulli:如果你有两个同名的模型(例如在不同的应用程序中),它将引发关于 related_name 的异常:冲突:app1.Title.tags:(字段.E304)“app1.Title.tags”的反向访问器与“app2.Title.tags”的反向访问器冲突。提示:在“app1.Title.tags”或“app2.Title.tags”的定义中添加或更改related_name 参数。
  • @HomunculusReticulli:如果设置,它将与related_name 参数一起使用,如果未设置,它将使用小写的modelname,不带下划线,因此对于Meal 模型,它是@987654336 @,对于TwoWords,是twowords
猜你喜欢
  • 2016-07-26
  • 2011-09-01
  • 1970-01-01
  • 2023-03-19
  • 2022-01-09
  • 2010-09-21
  • 2017-10-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多