我正在尝试做的事情:
我有模型Topic
和Entry
。 Entry
具有主题的ForeignKey。我需要列出主题(条件是用户在其中有条目)(在过去24小时内创建)。我还需要注释计数,它需要是用户写的最后一个条目之后创建的条目总数。 (更全面地说,您可以考虑一个收件箱,其中有包含未读邮件数量的对话列表。)
这是我想出的:
relevant_topics = (
Entry.objects.filter(author=user, date_created__gte=time_threshold(hours=24))
.values_list("topic__pk", flat=True)
.order_by()
.distinct()
)
qs = (
Topic.objects.filter(pk__in=relevant_topics).annotate(
latest=Max("entries__date_created", filter=Q(entries__author=user)),
count=Count("entries", filter=Q(date_created__gte=F("latest__date_created"))),
)
).values("title", "count")
将抛出:
FieldError: Cannot resolve keyword 'date_created' into field. Join on 'latest' not permitted.
我真的不知道Django本身是否不支持我编写的内容,或者我的解决方案有问题。我以为可以使用.extra()添加计数,但是我不知道该如何使用latest
注释。我真的很感激任何产生预期输出的查询。
我重新构建了您的查询,希望我正确理解了您的目标。我遇到了同样的错误。似乎与SQL评估查询的方式有关。我将您的疑问改写如下:
qs0 = Topic.objects.filter(
entries__author=user, entries__date_created__gte=time_threshold(24)).annotate(
latest=Max("entries__date_created")
)
qs1 = qs0.annotate(
count=Count("entries", filter=Q(entries__date_created__gte=F("latest")))
).values("title", "count")
因此,我首先过滤掉“用户”中有条目的最新主题,并用最新条目的日期(qs0)对其进行注释,然后尝试用所需的计数来对该查询进行注释。第一个查询执行了应该执行的操作;当我打印或评估它在列表中时,结果对我来说似乎是正确的(我使用了模拟数据)。但是通过第二个查询,我得到以下错误消息:
aggregate functions are not allowed in FILTER
LINE 1: ...") FILTER (WHERE "dummy_entry"."date_created" >= (MAX("dummy...
在Internet上进行的挖掘告诉我,这可能与SQL处理WHERE的方式有关。我尝试了MySQL和PostgreSQL,都产生了错误。在我看来,第二个查询在语法上是正确的,但是由于第一个查询在输入第二个查询之前没有进行评估,因此错误发生的方式。
无论如何,通过使用以下代码代替第二个查询,尽管以非常难看的方式,我仍然能够获得期望的结果(同样,如果我对您的理解正确的话):
dict = {}
for item in qs0:
dict[item.pk] = [item.title, item.latest, 0]
for entry in Entry.objects.all():
if entry.date_created >= dict[entry.topic.pk][1]:
dict[entry.topic.pk][2] += 1
我将qs0放入以pk为键的字典中,并手动对所有条目进行计数。
恐怕这是我所能做的最好的。我真的希望有人能提出一个更优雅的解决方案!