Реализуя рейтинг в Джанго - PullRequest
3 голосов
/ 26 сентября 2019

Что является лучшим способом реализации поля ставки в модели.Теперь у меня есть этот:

class Story(models.Model):
    ...
    rate = models.(help here)

class Rating(models.Model):
    rate = models.FloatField(validators=[MinValueValidator(0.0), MaxValueValidator(10.0)])
    story = models.ForeignKey(Story, on_delete=models.CASCADE)
    user = models.ForeignKey(User, on_delete=models.CASCADE)

Или есть другой способ сделать это?

Ответы [ 3 ]

2 голосов
/ 26 сентября 2019

Как сказал @Liudvikas Bajarunas, достаточно определить story как внешний ключ для модели Rating.Вы можете получить доступ к рейтингу истории, используя rating_set:

story_ratings = story.rating_set.all()

См. документацию по следующим отношениям в обратном направлении для получения дополнительной информации.

Вы можете комбинировать этот подход с агрегация , чтобы получить средний рейтинг истории:

class Story(models.Model):
    ...
    @property
    def average_rating(self):
        return self.rating_set.all().aggregate(Avg('rate'))['rate__avg']
2 голосов
/ 26 сентября 2019

Есть несколько улучшений, которые вы можете сделать:

  1. обычно лучше использовать get_user_model [Django-doc] для ссылки намодель пользователя, так как вы можете позже изменить свое мнение об этом;
  2. Возможно, вы захотите сделать user и story уникальными вместе, чтобы пользователь не мог сделать два рейтинга для одного и того же story;
  3. некоторые базы данных, такие как PostgreSQL, позволяют нам применять ограничения диапазона на уровне базы данных и, таким образом, делать его более безопасным.

, поэтому мы можем переписать его следующим образом:

from django.db import models
from django.contrib.auth import <b>get_user_model</b>
from django.db.models import CheckConstraint, Q, UniqueConstraint

class Rating(models.Model):
    rate = models.FloatField(validators=[MinValueValidator(0.0), MaxValueValidator(10.0)])
    story = models.ForeignKey(Story, on_delete=models.CASCADE)
    user = models.ForeignKey(<b>get_user_model()</b>, on_delete=models.CASCADE)

    class Meta:
        constraints = [
            <b>CheckConstraint(check=Q(rate__range=(0, 10)), name='valid_rate')</b>,
            <b>UniqueConstraint(fields=['user', 'story'], name='rating_once')</b>
        ]
2 голосов
/ 26 сентября 2019

Вы должны либо перейти с помощью сквозного поля, например:

class Story(models.Model):
    rates = models.ManyToManyField(User, through=Rating)

class Rating(models.Model):
    rate = models.FloatField(validators=[MinValueValidator(0.0), MaxValueValidator(10.0)])
    story = models.ForeignKey(Story, on_delete=models.CASCADE)
    user = models.ForeignKey(User, on_delete=models.CASCADE)

, или вы можете сделать это по-своему, используя отдельную модель, в которой в этом случае либо вы должны удалить поле rate из * 1005.* моделируйте или удаляйте поле story из Rating модели:

class Story(models.Model):
    ...
    # rate = models.(help here) No need anymore

class Rating(models.Model):
    rate = models.FloatField(validators=[MinValueValidator(0.0), MaxValueValidator(10.0)])
    story = models.ForeignKey(Story, on_delete=models.CASCADE)
    user = models.ForeignKey(User, on_delete=models.CASCADE)

, и ваш набор запросов будет выглядеть примерно так:

story.rating_set.all()

, который будет включать все оценки длявыбранный экземпляр истории.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...