Django 4 как сделать аннотацию над булевым полем queryset?
Я нашел это обсуждение аннотации над кверисетами. Интересно, было ли это когда-нибудь реализовано?
Когда я запускаю следующую аннотацию:
x = Isolate.objects.all().annotate(sum_shipped=Sum('shipped'))
x[0].sum_shipped
>>> True
shipped является булевым полем, поэтому я ожидал бы получить здесь количество случаев, когда shipped имеет значение True. Вместо этого я получаю True или 1. Это довольно неудобное поведение. На stackoverflow также есть обсуждение this. Однако оно охватывает только django 1.
Похоже, с тех пор это не затрагивалось. Является ли обсуждение во второй ссылке по-прежнему актуальным?
Есть ли лучший способ делать статистику с содержимым базы данных, чем этот, теперь, когда Django находится в версии 4?
Моя текущая база данных - sqlite3 для разработки и тестирования, но в производстве будет Postgres. Я бы очень хотел получить результаты, не зависящие от базы данных.
SUM(bool_field) в Oracle также вернет 1, потому что bool в Oracle - это просто бит (1 или 0). Postgres имеет специфический тип bool, и вы не можете суммировать True/False без неявного преобразования в int. Вот почему я говорю, что SUM(bool) случайно поддерживается только для подмножества баз данных. Тип возвращаемого поля основан на бэкенде get_db_converters и фактических значениях, которые возвращаются.
Я думаю, у вас есть несколько вариантов, аннотация не является одним из них в настоящее время.
from django.db.models import Sum, Count
# Use aggregate with a filter
print(Isolate.objects.filter(shipped=True).aggregate(Sum('shipped')))
# Just filter then get the count of the queryset
print(Isolate.objects.filter(shipped=True).count())
# Just use aggregate without filter (this will only aggregate/Sum the True values)
print(Isolate.objects.aggregate(Sum('shipped')))
# WON'T WORK: annotate will only annotate on that row whatever that row's value is, not the aggregate across the table
print(Isolate.objects.annotate(sum_shipped==Count('shipped')).first().sum_shipped)