Django ORM - .exclude Q vs exclude(ids_in=ids) с Subquery, annotate
Django Queryset exclude()
не работает, как ожидалось, с выражениями Q
Я пытаюсь исключить некоторые Project
объекты из моего набора запросов, используя два разных метода: один основан на идентификаторах, а другой - на Q
выражении для аннотированных данных. Однако каждый из этих методов дает разные результаты, и я не могу понять, почему. Версия с выражением Q
возвращает пустой кверисет, хотя это не должно быть так.
Вот соответствующий код:
def check_exclusion():
# Subquery to get the latest active ReportCalculation message for each project
latest_calc_message = ReportCalculation.objects.filter(
project=OuterRef('pk'),
is_active=True
).order_by('-id').values('message')[:1]
# Annotate projects with the latest calculation message
projects_with_messages = Project.objects.annotate(
latest_message=Subquery(latest_calc_message)
).filter(
end_date__lt=date.today(), # Project must have ended
is_active=True # Project must be active
).distinct()
# Exclude based on latest_message
excluded_projects = projects_with_messages.filter(
Q(latest_message__in=("Scheduled.", "Finished successfully.", "Processing ..."))
| Q(latest_message__startswith="Error")
).distinct()
ids = excluded_projects.values_list("id", flat=True)
# Exclude using Q expression directly on the annotated field
remaining_projects = projects_with_messages.exclude(
Q(latest_message__in=("Scheduled.", "Finished successfully.", "Processing ..."))
| Q(latest_message__startswith="Error")
).values('id', 'latest_message') # Get IDs and messages for verification
print(projects_with_messages.exclude(id__in=ids)) # First method using IDs
print(remaining_projects.values_list("id", flat=True)) # Second method using Q expression
return list(excluded_projects), list(remaining_projects)
Что я наблюдаю:
- При исключении проектов по идентификаторам (т.е.
exclude(id__in=ids)
) исключение работает, как и ожидалось. - При использовании выражения
Q
непосредственно наlatest_message
(exclude(Q(...))
) получается пустой набор запросов, чего не должно быть.
То, что я ожидал:
Оба метода исключения должны возвращать одинаковые результаты или, по крайней мере, похожие. Но сейчас второй подход, использующий выражение Q
, ничего не возвращает, и я не могу понять, почему.
Кто-нибудь знает, почему выражение Q
ведет себя таким образом? Может быть, что-то не так с тем, как я аннотирую или фильтрую данные?