Система рейтинга Django
Всем здравствуйте!
Столкнулся с проблемой, помогите решить
У меня есть посты, и к ним можно добавлять комментарии с рейтингом от 1го до 5 В комментариях все хорошо выводится, но мне нужно вывести средний рейтинг для каждого поста. Уже голову сломал
Вот мои модели:
class Post(models.Model):
school_name = models.CharField(max_length=200, default='')
country = models.CharField(max_length=200, default='KZ')
city = models.CharField(max_length=200, default='')
content = models.TextField()
website = models.CharField(max_length=200, default='')
your_email = models.EmailField(default='')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
author = models.ForeignKey(User, on_delete=models.CASCADE)
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
author = models.ForeignKey(User, on_delete=models.CASCADE)
text = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
score = models.IntegerField(default=0, validators=[MaxValueValidator(5), MinValueValidator(1)])
def __str__(self):
return self.text
def get_absolute_url(self):
return reverse('post_detail', args=[str(self.post.id)])
Мне нужно сделать вюьюху и темплейт, пока они такие
Вьюха:
def post_list(request):
posts = Post.objects.all()
return render(request, 'post_list.html', {'posts': posts})
Тепмлейт:
<a class="nav-link px-2 text-muted" href="{% url 'posts:post_detail' post.id %}">
<h2>{{ post.school_name }}</h2>
<p>Автор: {{ post.author }}</p>
<p>Опубликовано: {{ post.created_at }}</p>
<p>Обновлено: {{ post.updated_at }}</p>
<a href="{% url 'posts:post_edit' post.id %}">Редактировать</a>
<a href="{% url 'posts:post_delete' post.id %}">Удалить</a>
</a>
Ответы (3 шт):
Я бы попробовал нечто подобное:
class Post(models.Model):
school_name = models.CharField(max_length=200, default='')
country = models.CharField(max_length=200, default='KZ')
city = models.CharField(max_length=200, default='')
content = models.TextField()
website = models.CharField(max_length=200, default='')
your_email = models.EmailField(default='')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
author = models.ForeignKey(User, on_delete=models.CASCADE)
def rating(self):
comments = self.comments.all()
rating = 0
for i in comments:
rating = rating + i.score
return rating/len(comments)
Писал по памяти, поэтому могут быть ошибки. В целом идея должна быть понятна.
Посчитать общее количество комментариев и посчитать среднее арифметическое.
post_list(request):
comments = Comment.objects.filter(post=request.post)
number_comments = len(comments)
sum_score = 0
for comment in comments:
sum_score += comment.score
rate_post = sum_score / number_comments
return render(request, 'post_list.html', {'posts': posts, 'rate_post': rate_post})
Если нужно рейтинг именно поста, то нужно добавить рейтинг в модель поста, а не комментария. Или можно сделать так чтобы с новым комментарием рейтинг не добавлялся, а обновлялся уже имеющийся (если таковой есть). В таком случае нужно сумму комментариев отфильтровать по автору.
Решил немного по другому добавил отображение среднего рейтинга в детальное представление поста вышло так
def post_detail(request, pk):
post = Post.objects.get(pk=pk)
comments = post.comments.all()
comment = Comment.objects.filter(post=post)
ratings = Rating.objects.filter(post=post).all()
rating = ratings.values_list('rating')
average_rating = ratings.aggregate(Avg('rating'))['rating__avg']
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.post = post
comment.user = request.user
comment.save()
return redirect('posts:post_detail', pk=post.pk)
else:
form = CommentForm()
return render(request, 'post_detail.html', {'post': post, 'comments': comments, 'form': form, 'ratings': ratings, 'average_rating': average_rating, 'rating': rating})