Как сделать статистику уникальных значений в полях модели в Django

O
На сайте с 09.04.2018
Offline
3
1327

Всем привет!

Я пишу view в которой под таблицей значений из модели должна быть таблица со статистикой уникальных значений и самых повторяющихся. То есть надо пересчитать вхождения каждого значения по полям в query_set, например GET: 10 штук, POST: 15 штук, IP: 45 штук, TOP 10 IPs: [список]. Как это можно сделать в Django?

S
На сайте с 23.05.2004
Offline
315
#1

Функции агрегации или банально raw_query с запросом с группировкой по значению.

https://docs.djangoproject.com/en/1.11/topics/db/aggregation/

Это просто подпись.
O
На сайте с 09.04.2018
Offline
3
#2

Я посмотрел, про аннотацию и агрегацию, возник вопрос. Если я хочу сосчитать уникальные IP, пересчитать все методы и их количество по именам, сумму байтов ответа по всем запросам, могу ли я сделать это одним запросом? Пока я нашел только такое:

.values('IP').annotate(Sum('ip'))

А хочется увидеть такое:

.values([fields_list]).annotate(Sum('ip'), Sum('method_get'), Sum('method_post'))

Как это сделать?

S
На сайте с 23.05.2004
Offline
315
#3

Никак. Нельзя делать индивидуальные группировки по разным полям в одном запросе.

Правда есть один модуль https://github.com/henriquebastos/django-aggregate-if/ , возможно с ним и получится за один запрос такое получить. Но скорее всего сделает это в куче вложенных запросов.

O
На сайте с 09.04.2018
Offline
3
#4

Я попробовал сделать values(param1).annotate(param2), но вместо GROUP_BY происходит фильтрация, и подсчет доступен только для строк по отдельности, как будто values() не написано.

result = Entries.objects.values('remote_host').annotate(remote_host_count=Count('remote_host'),

method_count=Count('method'),

bytes_sum=Sum('bytes_returned'))

В браузере вместо таблицы со всеми параметрами запроса только IP адреса, то есть остальные пустые. В консоли

print(result[1])

{'remote_host': '46.72.177.4', 'remote_host_count': 18, 'method_count': 18, 'bytes_sum': 78813}

Можно ли сделать вот так:

result = Entries.objects.all().annotate(Entries.objects.values('method').annotate(method_count=Count('method')))

---------- Добавлено 11.04.2018 в 12:15 ----------

Я уже разобрался с предыдущим вопросом. теперь я думаю как сделать сортировку списка словарей в QuerySet.

Все это выглядит вот так:

<QuerySet [{'method': 'GET', 'method_count': 96, 'bytes_sum': 409248}, {'method': 'POST', 'method_count': 96, 'bytes_sum': 431424}]>

Надо сделать сортировку по значению ключа bytes_sum по убыванию. Сортировать словари в списках я умею, а как сделать в QuerySet?

S
На сайте с 23.05.2004
Offline
315
#5

Гугл же в помощь, примеров сортировки куча. Только сначала из кверисета перенести в обычный массив.


>>> student_tuples = [ ('john', 'A', 15),
('jane', 'B', 12),
('dave', 'B', 10),
]
>>> sorted(student_tuples, key=lambda student: student[2]) # sort by age
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий