Как выполнить аналитику по нескольким подсчетам с помощью django?
У меня есть аналитическая панель - в основном она показывает обзор данных. Допустим, у нас есть таблица с именем "Records"
В моей панели аналитики мне нужно показать различные подробности о записях конкретного пользователя:
user = Records.objects.filter(id=pk)
В результате мы получаем все записи, связанные с пользователем, теперь нужно показать различные аналитические данные, как показано ниже,
Total Records,
Total Records by Today
Total Records by Week
Total Records by Month
Total Active Records // Records which has status == active
Total InActive Records // Records which has status == inactive
Как все это сделать? В ходе исследования я нашел несколько вариантов, которым можно следовать,
Вариант 1: Выполнить отдельный запрос для каждой потребности
.
Вариант 2: Выполнить выборку всех данных и выполнить вышеуказанные вычисления в представлении и отправить как контекст
Как с этим быть? Я также планирую использовать графики
Class Records:
owner = models.ForeignKey(User, on_delete=models.CASCADE)
name = models.CharField(max_length=120)
code = models.CharField(max_length=16)
type = models.CharField(max_length=32)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now = True)
Если вы планируете использовать библиотеку фронтенда, такую как Chart.js (которую я настоятельно рекомендую), у вас есть два подхода:
Создайте структуру данных для каждого запроса на бэкенде и передайте все данные сразу на фронт-энд
.- Преимущества:
- После того, как данные доступны во фронт-энде, скрипты рендеринга будут выполняться намного быстрее (например, изменение графиков)
- Недостатки
- Инициализация данных может занять больше времени, так как бэкэнд делает много дел одновременно .
- Код бэкенда может стать избыточным или чрезмерно сложным и трудно управляемым
- Преимущества:
Создайте конечную точку на бэкенде и динамически запрашивайте ее с фронтэнда
.- Преимущества:
- Бэкэнд выполняет меньше работы для каждого отдельного запроса, поэтому загрузка происходит быстрее
- Недостатки:
- Пользователи, которые постоянно перелистывают графики, могут испытывать задержку при ожидании выполнения каждого запроса .
- Преимущества:
Очевидно, что это не исчерпывающий список плюсов и минусов каждого варианта, хотя обычно я выбираю вариант 2 в своих проектах.
В идеале Делайте работу с базой данных в базе данных, а не в Python, если только у вас нет бюджетных ограничений на использование службы базы данных (хотя в этом случае работа будет переложена на ваш app worker). Поскольку вас интересует только количество элементов, вы можете просто использовать QuerySet.count(). См. раздел Field Lookups для справки о запросах, сделанных ниже.
from datetime import datetime, date
user_records = Records.objects.filter(owner=some_user)
today = date.today()
total_records = user_records.count()
total_records_today = user_records.filter(created_at__date=today).count()
total_records_week = user_records.filter(created_at__year=today.year, created_at__week=today.isocalendar()[1]).count()
total_records_month = user_records.filter(created_at__year=today.year, created_at__month=today.month).count()
total_records_active = user_records.filter(status="active").count()
total_records_inactive = user_records.filter(status="inactive").count()
Или вы также можете вручную выполнить подсчет по всем записям:
for rec in user_records:
if rec.created_at.date() == today:
total_records_today += 1
if rec.created_at.date().isocalendar()[1] == today.isocalendar()[1]:
total_records_week += 1
...
Ор:
total_records_today = len(list(filter(lambda rec: rec.created_at.date() == today, user_records)))
total_records_week = len(list(filter(lambda rec: rec.created_at.date().isocalendar()[1] == today.isocalendar()[1], user_records)))
...