Я перестроил ваш запрос, надеюсь, я правильно понял вашу цель. Я пришел с той же ошибкой. Кажется, это как-то связано с тем, как 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...
Копание по inte rnet говорит мне, что это может быть связано с тем, как 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 и сделал подсчитайте все записи вручную.
Боюсь, это лучшее, что я могу сделать. Я искренне надеюсь, что кто-то придумает более элегантное решение!
РЕДАКТИРОВАТЬ после прочтения ответа Krysotl:
Не окончательный ответ, но, возможно, это поможет. В большинстве случаев WHERE нельзя использовать перед агрегатными функциями, см. Агрегатная функция в SQL WHERE-Clause . Иногда это можно исправить, заменив WHERE на HAVING в SQL. Django может обрабатывать необработанные SQL запросы, см. https://docs.djangoproject.com/en/3.0/ref/models/expressions/#raw - sql -выражения . Поэтому я попробовал следующее:
sql_command = '''SELECT entry.topic_id, topic.title, entry.date_created, COUNT(entry.id) AS id__count FROM entry
INNER JOIN topic ON (entry.topic_id = topic.id) GROUP BY entry.topic_id, topic.title, entry.date_created
HAVING entry.date_created > (SELECT MAX(U0.date_created) AS latest
FROM entry U0 WHERE (U0.author_id = 1 AND U0.date_created >= '2020-04-09 16:31:48.407501+00:00'
AND U0.topic_id = (entry.topic_id)) GROUP BY U0.topic_id)'''
qs = Entry.objects.annotate(val=RawSQL(sql_command, ()))
Другими словами: поместите GROUP BY перед WHERE и замените WHERE на HAVING. К сожалению, это все еще дало мне ошибки. Боюсь, мне недостаточно эксперта SQL, чтобы решить эту проблему, но, возможно, это путь вперед.