Django ORM версия SQL COUNT (DISTINCT <столбец>)
Мне нужно заполнить шаблон сводкой активности пользователя в простой системе обмена сообщениями. Для каждого отправителя сообщения я хочу, чтобы количество отправленных сообщений и количество отдельных получателей.
Здесь приведен упрощенный вариант модели:
class Message(models.Model):
sender = models.ForeignKey(User, related_name='messages_from')
recipient = models.ForeignKey(User, related_name='messages_to')
timestamp = models.DateTimeField(auto_now_add=True)
Вот как я сделал бы это в SQL:
SELECT sender_id, COUNT(id), COUNT(DISTINCT recipient_id)
FROM myapp_messages
GROUP BY sender_id;
Я читал документацию по агрегации в запросах ORM, и хотя annotate() может обрабатывать первый столбец COUNT, я не вижу способа получить результат COUNT (DISTINCT) (даже extra (select = {}) не работает, хотя кажется, что он должен). Может ли это быть переведено в запрос ORM Django или я должен просто придерживаться необработанного SQL?
Ответы
Ответ 1
Вы можете использовать разные и подсчеты вместе, как видно из этого ответа: fooobar.com/questions/169921/...
В вашем случае:
SELECT sender_id, COUNT(id), COUNT(DISTINCT recipient_id)
FROM myapp_messages
GROUP BY sender_id;
станет:
Message.objects.values('sender').annotate(
message_count=Count('sender'),
recipient_count=Count('recipient', distinct=True))
Ответ 2
from django.db.models import Count
messages = Message.objects.values('sender').annotate(message_count=Count('sender'))
for m in messages:
m['recipient_count'] = len(Message.objects.filter(sender=m['sender']).\
values_list('recipient', flat=True).distinct())