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]
в следующем диктанте, но это уже разделение волос!