在后续注释中使用注释值将引发FieldError

问题描述 投票:0回答:1

我正在尝试做的事情:

我有模型TopicEntryEntry具有主题的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注释。我真的很感激任何产生预期输出的查询。

python django django-orm
1个回答
0
投票

我重新构建了您的查询,希望我正确理解了您的目标。我遇到了同样的错误。似乎与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为键的字典中,并手动对所有条目进行计数。

恐怕这是我所能做的最好的。我真的希望有人能提出一个更优雅的解决方案!

© www.soinside.com 2019 - 2024. All rights reserved.