Проблема с выполнением подсчета методом группировки с использованием аннотированного поля

Context

У меня есть таблица/модель под названием Article.

В этой модели у меня есть несколько полей, таких как срок действия, видимость и статус. Эти поля определяют, должна ли статья отображаться или нет. По сути, желаемая логика выглядит следующим образом:

display = True
if status == 'Private'; display = False
if visibility == False; display = False
... 

Для простоты в этом посте я буду использовать только одно поле: status. Поле status представляет собой CharField с вариантами выбора: 'Private' или 'Public'.

Для того чтобы разработать логику отображения, я использую аннотацию. Это относительно просто:

all_articles = Article.objects.annotate(
    display=Case(When(status='Private', then=Value(False)), default=Value(True), output_field=models.BooleanField())
)

displayed_articles = all_articles.filter(display=True)
notdisplayed_articles = all_articles.filter(display=False)

Гол

При такой настройке я хотел бы использовать Django ORM для выполнения подсчета с группировкой по, чтобы определить, сколько статей отображается, а сколько нет.

В табличном формате SQL результат будет выглядеть следующим образом:

display count
True 500
False 2000

Проблема

Это естественный способ достижения моей цели:

queryset = Article.objects.annotate(
    display=Case(
        When(status='Private', then=Value(False)), default=Value(True), output_field=models.BooleanField()
    )
).values('display').annotate(count=Count('id')).order_by()

print(queryset)

Ожидание

Я ожидаю что-то вроде этого:

<QuerySet [{'display': True, 'count': 500}, {'display': False, 'count': 2000}]>

Ошибка

Однако я получаю следующее:

django.db.utils.ProgrammingError: ('42000', "[42000] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Column 'blog_article.status' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause. (8120) (SQLExecDirectW)")

Почему это происходит и как я могу это обойти?

Исследование SQL-запроса

Я изучил сгенерированный SQL-запрос следующим образом:

print(queryset.query)
SELECT CASE
        WHEN [blog_article].[status] = Private THEN False
        ELSE True
    END AS [display],
    COUNT_BIG([blog_article].[id]) AS [count]
FROM [blog_article]
GROUP BY CASE
        WHEN [blog_article].[status] = Private THEN False
        ELSE True
    END

Общая структура запроса выглядит нормально, мне нужно было лишь внести в него небольшие изменения. Приведенный ниже запрос был успешно выполнен по отношению к базе данных.

SELECT CASE
        WHEN [blog_article].[status] = "Private" THEN 1
        ELSE True
    END AS [display],
    COUNT_BIG([blog_article].[id]) AS [count]
FROM [blog_article]
GROUP BY CASE
        WHEN [blog_article].[status] = "Private" THEN 0
        ELSE True
    END

Я также проверил выполнение этого запроса, используя pyodbc, и он был выполнен успешно.

Вернуться на верх