Django. Статистика на сайте цитат

Есть проект - сайт, в котором пользователи могут постить цитаты, указывать автора цитаты и добавлять к ним категории. Смысл в том, что это будет сайт для ограниченного числа людей, поэтому определенные юзеры уже будут указаны в базе данных, то есть фиксированное число пользователей, больше не будет. Эти то юзеры и будут авторами данных цитат, а также редакторами: один человек что-то сказал(автор цитаты), второй(редактор цитаты) это запостил на сайте и указал автора. Так вот, мне бы хотелось иметь связь между Автором(не редактором) и цитатой, к которой его отнесли. Идея такая, чтобы у определенного юзера имелась статистика, в которой есть информация о том, к какой Категории цитат чаще приписывают Автора. Например, из категорий цитат "любовь", "смех" и "грусть" меня бы чаще заносили в Категорию "смех", ведь я чаще шучу, соответственно, цитаты на сайте, скорее всего, имели бы похожую категорию.

from django.db import models
from author.models import Profile


class QuotesHonors(models.Model):
quotes = models.TextField()
editor = models.ForeignKey(Profile, on_delete=models.DO_NOTHING,
                           related_name='quotes_editor')
author = models.ForeignKey(Profile, on_delete=models.DO_NOTHING,
                           related_name='quotes_author')
category = models.ManyToManyField(
    'Category', related_name='quotes_category')
updated = models.DateTimeField(auto_now=True)
created = models.DateTimeField(auto_now_add=True)

def __str__(self) -> str:
    return str(self.quotes[:30])


class Category(models.Model):
title = models.CharField(max_length=150, db_index=True)

def __str__(self) -> str:
    return str(self.title)


class Like(models.Model):
user = models.ForeignKey(Profile, on_delete=models.CASCADE,
                         related_name='user_like')
quotes = models.ForeignKey(QuotesHonors, on_delete=models.CASCADE,
                           related_name='quotes_like')
updated = models.DateTimeField(auto_now=True)
created = models.DateTimeField(auto_now_add=True)


class Comment(models.Model):
user = models.ForeignKey(Profile, on_delete=models.CASCADE,
                         related_name='user_comment')
quotes = models.ForeignKey(QuotesHonors, on_delete=models.CASCADE,
                           related_name='quotes_comment')
body = models.TextField(max_length=300)
updated = models.DateTimeField(auto_now=True)
created = models.DateTimeField(auto_now_add=True)

from django.db import models
from django.contrib.auth.models import User


class Profile(models.Model):
first_name = models.CharField(max_length=150)
last_name = models.CharField(max_length=150)
user = models.OneToOneField(User, on_delete=models.CASCADE)
email = models.EmailField(max_length=250, blank=True)
# avatar = models.ImageField(default='avatars/gosling.jpg', upload_to='avatars/')
updated = models.DateTimeField(auto_now=True)
created = models.DateTimeField(auto_now_add=True)

def __str__(self) -> str:
    return str(self.first_name) + ' ' + str(self.last_name)

Давно не писал запросы в DjangoORM, но, что-то близкое к вашему решению будет выглядеть так: предположим, что user это объект модели Profile, тогда запрос user.quotes_author.all() вернет вам QuerySet из всех цитат пользователя. Tак как нам нужно узнать какая категория пользуется популярностью, добавим в выборку только интересующее нас поле: user.quotes_author.all().values('category')

Далее, подсчитаем количество цитат в каждой категории и отсортируем по убыванию:

from django.db.models import Count
user.quotes_author.all().values('category').annotate(total=Count('category')).order_by('total')

В результате вернется QuerySet с категориями, отсортированными по убыванию, т.е. самая популярная будет на 0 позиции. Можно получить ее сразу, добавив .first() метод к запросу.

Более подробно про values почитать тут, про annotate тут, а про Count - тут.

Вернуться на верх