Джанго ОРМ отношения один-ко-многим - PullRequest
0 голосов
/ 25 июня 2019

У меня есть модель:

class Product(models.Model):
    title = models.CharField(max_length=200)
    url = models.URLField()
    pub_date = models.DateTimeField()
    votes_total = models.IntegerField(default=1)
    image = models.ImageField(upload_to='images/')
    icon = models.ImageField(upload_to='images/')
    body = models.TextField()
    hunter = models.ForeignKey(User, on_delete=models.CASCADE)

Теперь я хотел бы добавить функциональность upvoters , чтобы узнать, за какие продукты уже проголосовал пользователь. Мне нужно, чтобы пользователи могли голосовать за один продукт только один раз.
Опять же, чтобы уточнить - пользователь может голосовать за несколько продуктов, но только один раз за каждый.
Таким образом, отношение составляет один продукт - много пользователей (upvoters) .
Я попытался добавить следующее поле, но не могу выполнить миграцию, даже если предусмотрено поле по умолчанию. Также я попытался очистить базу данных, но снова не могу заставить ее работать.

upvoters = models.ForeignKey(User, on_delete=models.CASCADE, related_name='upvoted')

Полагаю, это работает следующим образом:

Поле для определения проголосовавших продуктов. Чтобы проверить, проголосовал ли пользователь за продукт, позвоните: User.upvoted.filter(id=product.id).count() == 1 Это означает, что пользователь уже проголосовал за этот продукт.

Что не так? Что я должен изменить, чтобы это работало?

1 Ответ

3 голосов
/ 25 июня 2019

Вам нужно будет использовать ManyToMany, но вы можете использовать настраиваемую сквозную модель, чтобы ограничить комбинации продуктов / голосов.

К классу продукта добавьте:

voters = models.ManyToManyField(User, through='ProductVote', related_name='product_voters')

Затем добавьтенастраиваемая модель:

class ProductVote(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    product = models.ForeignKey(Vote, on_delete=models.CASCADE)

    class Meta:
        unique_together = ['user', 'product']

Если вы попытаетесь добавить голос за ту же комбинацию пользователь / продукт, будет сгенерирована ошибка IntegrityError.

...