Django наиболее эффективный способ подсчета пользователей и типов

В моем проекте django у меня есть модель пользователя, и я хочу подсчитать различные статусы пользователей. Я не уверен в том, как лучше всего подойти к этому, так как это модель самого верхнего уровня, поэтому я не думаю, что смогу использовать annotate.

Я пробовал, но, конечно, я на

workers = get_user_model().objects.annotate(
            not_active_workers=Count("id", filter=Q(is_active=False, status=0))
        ).annotate(
            active_not_complete_workers=Count("id", filter=Q(is_active=True, profile_completed=False, status=0))
        ).annotate(
            complete_applicant_workers=Count("id", filter=Q(is_active=True, profile_completed=True, status=0))
        ).annotate(
            former_workers=Count("id", filter=Q(is_active=False, status=2))
        ).annotate(
            accepted_workers=Count("id", filter=Q(is_active=False, status=1))
        ).filter(role=2)

dict(
  not_active=workers[0].not_active_workers,
  active_not_complete=workers[0].active_not_complete_workers,
  complete_applicant=workers[0].complete_applicant_workers,
  former=workers[0].former_workers,
  accepted=workers[0].accepted_workers, 
)

Другой способ - count() для каждого фильтра, но это будет несколько запросов. Я думаю, что эти способы будут довольно быстрыми, но, возможно, я упускаю более простой способ подсчета всех запросов как набора данных за 1 удар?

Насколько я знаю, нет более простого способа сделать это, потому что ваши фильтры сложные и существуют как Q() объекты внутри Count фильтра. Агрегат здесь не подходит, а другой метод использования .values() не сработает - пример:

User.objects.values('type').order_by('type').annotate(user_count=Count('type'))
# Output: [{'type': 'user', 'user_count': 3}, {'type': 'admin', 'user_count': 1}, ...

Единственное улучшение, которое я могу предложить - это переформатирование:

workers = get_user_model().objects.annotate(
        not_active_workers=Count("id", filter=Q(is_active=False, status=0)),
        active_not_complete_workers=Count("id", filter=Q(is_active=True, profile_completed=False, status=0)),
        complete_applicant_workers=Count("id", filter=Q(is_active=True, profile_completed=True, status=0)),
        former_workers=Count("id", filter=Q(is_active=False, status=2)),
        accepted_workers=Count("id", filter=Q(is_active=False, status=1))
    ).filter(role=2)

Вы также могли бы добавить .first() и убрать все обозначения [0] в следующем диктанте, но это уже разделение волос!

Back to Top