【发布时间】:2022-12-06 08:05:50
【问题描述】:
这是我的模型的简化表示:
class Post(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
template_id = models.IntegerField(null=True)
...
我想要做的是显示用户使用模板的次数。所以当我列出模板时,我希望能够说Used by X users。主要的吸引力是我不想只计算一个用户一次(所以如果一个用户两次使用一个模板,他们仍然算作“一个用例”)。所有 stackoverflow 帖子都在谈论做这样的事情:
counts = Post.objects.all().values("template_id").order_by().annotate(count=Count("template_id"))
但这显然重复计算了两次使用同一模板的用户。我能够像这样在template_id 和user 配对上做一个不同的:
Post.objects.all().values("template_id", "user__id").distinct()
# Printing this out, I get 2 distinct entries in the QuerySet:
# <QuerySet [{'template_id': 1, 'user__id': 1}, {'template_id': 1, 'user__id': 2}]>
但是,当我尝试获取 template_id 的计数(下面的代码)时,它似乎忽略了 distinct 并且仍然重复计算用户。
Post.objects.all().values("template_id", "user__id").distinct().values("template_id").annotate(count=Count("template_id"))
# Printing this out I get `count` = 3, which double counts a user.
# <QuerySet [{'template_id': 1, 'count': 3}]>
对于它的价值,我写了一个快速测试用例,它是失败的。
user1 = baker.make("User")
user2 = baker.make("User")
# Populate posts
quest1 = baker.make("post.Post", user=user1, template_id=1)
quest2 = baker.make("post.Post", user=user1, template_id=1) # Duplicate shouldn't count
quest3 = baker.make("post.Post", user=user2, template_id=1)
【问题讨论】:
-
values后跟 annotate 做一个分组,你应该只使用countmethod -
@AbdulAzizBarkat 所以这里的问题是我在产品中有数百/数千个模板。执行此操作的唯一方法是实际遍历每个模板并手动获取每个模板的计数吗?有没有更有效的方法来做到这一点?
-
该模板看起来像一个单独的实体,为什么
template_id是一个整数字段而不是外键?如果您有一个单独的模板模型和适当的外键等,您可能可以从该模型中查询。您可以尝试使用distinctargument 到Count也许这有帮助? -
是的,它绝对应该是另一个模型。我是几年前创建的,所以我的模型并不是设计得最好的。我有一个非常大的 json,其中包含所有模板。我很快就会将其转换为 Django 模型。我试一试不同的论点!
-
distinct in count 不起作用。它为每个模板 ID 提供了 1 个计数。
标签: django