#django #django-models #rating #rating-system
#django #django-модели #Оценка #рейтинговая система
Вопрос:
Я новичок в Django, перешел с PHP на движок Propel ORM. Итак, вот что я сейчас делаю в Django. На моем веб-сайте есть несколько моделей, таких как
- Книга,
- Издатель,
- Комментарий,
- Статья и так далее (это не главное)
Каждое из них может понравиться или не понравиться пользователю (только один раз), изменяя рейтинг модели на 1 или -1.
С точки зрения PHP я бы создал поведение, например. «Rateable», который добавлял бы некоторые поля и методы к исходной модели и классу запроса (например, get_rating()
, order_by_rating()
и т.д.) И создавал отдельную таблицу для каждой модели, например. book_rating_history
которая будет содержать все оценки для каждого объекта, чтобы определить, может ли пользователь изменить оценку (или показать все оценки объекта, если необходимо). Итак, все, что мне нужно было бы сделать, это указать поведение «Rateable» в объявлении модели, и это все. Все остальное выполняется автоматически.
Вопрос в том, как решить это в Django? Как правильно моделировать? Какие методы вы используете в подобных случаях?
Ответ №1:
Вы захотите хранить рейтинги и книги отдельно, что-то вроде этого (непроверенное).
from django.contrib.auth.models import User
from django.db import models
from django.db.models import Sum
class BookRating(models.Model):
user = models.ForeignKey(User)
book = models.ForeignKey('Book')
# you'll want to enforce that this is only ever 1 or -1
rating = models.IntegerField()
class Meta:
unique_together = (('user', 'book'),)
class Book(models.Model):
title = models.CharField(max_length = 50)
def rating(self):
return BookRating.objects.filter(book = self).aggregate(Sum('rating'))
unique_together
обеспечивает, чтобы каждый пользователь мог оценить данную книгу только один раз.
Затем вы можете использовать это что-то вроде:
book = Book.objects.get(pk = 1)
rating = book.rating()
Добавьте комментарий, если у вас возникли проблемы с этим — я не тестировал это, но, надеюсь, этого достаточно, чтобы вы начали.
Вероятно, вы можете избежать того, чтобы каждый объект (книги, издатели, комментарии, статьи) имел отдельный объект оценки, используя типы контента, если хотите.
В качестве альтернативы вы могли бы рассмотреть существующие повторно используемые приложения, которые обрабатывают лайки, такие как django-likes или phileo.
Комментарии:
1. Бонусная функция: пользователь может изменить свой рейтинг позже.
Ответ №2:
Вы можете определить специальные методы (например, vote, get_rating и т.д.) Только один раз в абстрактной модели, А затем создать свои «Оцениваемые» модели, используя эту.
class Rateable(models.Model):
class Meta:
abstract = True
def vote(self, *args, **kwargs):
...
def rating(self, *args, **kwargs):
...
class Book(Rateable):
...
Также лучше использовать единую модель для хранения рейтинговых данных и типов контента, как заметил Доминик Роджер
Комментарии:
1. Спасибо, ребята, я прочитал документацию для фреймворка типов контента и решил использовать ее для рейтингов, тегов и подобных вещей.