Эффективный способ обработки данных для количества просмотров с датами
Я ищу более эффективный способ реализации представленного кода, который извлекает количество просмотров для объекта в диапазоне дат (start_date
и end_date
). Текущий код достигает ожидаемого результата, преобразуя данные в структуру словаря с names
и соответствующими ежедневными представлениями count
. Однако я считаю, что существует более оптимизированный подход.
Вот фрагмент кода для справки:
models.py
class Ad(models.Model):
ad_type = models.ForeignKey(to=AdType, on_delete=models.CASCADE, related_name="ad")
name = models.CharField(max_length=256)
image = models.ImageField(upload_to="ads")
is_active = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
class AdStat(models.Model):
class StatType(models.TextChoices):
VIEWS = "views", _("Views")
CLICKS = "clicks", _("Clicks")
ad = models.ForeignKey(to=Ad, on_delete=models.CASCADE, related_name="ad_stat")
stat_type = models.CharField(max_length=10, choices=StatType.choices)
created_at = models.DateTimeField(auto_now_add=True)
views.py
@staff_member_required
def ads_number_of_views(request):
start_date = request.GET.get("start_date")
end_date = request.GET.get("end_date")
ads = (
AdStat.objects.filter(ad__is_active=True, ad__ad_type__slug="desktop-hader")
.select_related("ad")
.values("ad__name", "created_at__date")
.annotate(view_count=Count("id"))
.order_by("created_at__date")
)
if start_date and end_date:
ads = ads.filter(created_at__gte=start_date, created_at__lte=end_date)
elif start_date:
ads = ads.filter(created_at__gte=start_date)
elif end_date:
ads = ads.filter(created_at__lte=end_date)
ads_data = []
for item in ads:
ad_name = item["ad__name"]
date_str = str(item["created_at__date"])
count = item["view_count"]
found = False
for entry in ads_data:
if entry["name"] == ad_name:
entry["number_of_views"].append({"created_at": date_str, "count": count})
found = True
break
if not found:
ads_data.append({"name": ad_name, "number_of_views": [{"created_at": date_str, "count": count}]})
return JsonResponse(ads, safe=False)
Ожидаемый результат.
Код успешно возвращает ответ в формате JSON со следующей структурой:
[
{
"name": "ad1",
"number_of_views": [
{"created_at": "2024-03-28", "count": 18},
{"created_at": "2024-03-30", "count": 47}
]
},
{
"name": "ad2",
"number_of_views": [
{"created_at": "2024-03-30", "count": 24},
{"created_at": "2024-03-31", "count": 33}
]
}
]
Наряду с эффективностью, я хотел бы включить функцию фильтрации для Chart.js. В идеале, пользователь должен иметь возможность выбирать между просмотром данных по дням, месяцам и годам. Я готов рассмотреть альтернативные подходы с использованием ORM-возможностей Django или других оптимизаций.