Restricting single Rating on each Book by each Use

2019-07-31 18:13发布

Edited Title : Limit multiple "Many to One" fields into "One to One" association : Django

We've Book, User and Rating as Django model.

  • Each Book has many Ratings
  • Each Rating has one Book
  • Each User has many Ratings
  • Each Rating has one User

For Book

class Book(models.Model):
    isbn = models.CharField(max_length=32)
    title = models.CharField(max_length=256)

    def __str__(self):
        return self.title 

For Book Rating

class BookRating(models.Model):
    book = models.ForeignKey(Book, on_delete=models.CASCADE)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    rating = models.SmallIntegerField(choices=[(i, i) for i in range(1, 6)])

    def __str__(self):
        return self.rating

Problem Statement

How can I ensure that each User has atmost one rating on each book?

1条回答
Fickle 薄情
2楼-- · 2019-07-31 18:49

Just do

class BookRating(models.Model):
    book = models.ForeignKey(Book, on_delete=models.CASCADE)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    rating = models.SmallIntegerField(choices=[(i, i) for i in range(1, 6)], default=1)

    class meta:
        unique_together = ('book','user')

Your models do implement a many to many relationship, however you are not getting full access to the django ManyToMany functionality. I recommend you do something like this:

class Book(models.Model):
    isbn = models.CharField(max_length=32)
    title = models.CharField(max_length=256)
    ratings = models.ManyToManyField(User,through='BookRating')

When you do this your BookRating can remain unchanged, but the small change to the Book model gives you full access to the api described here: https://docs.djangoproject.com/en/1.10/topics/db/examples/many_to_many/

What's interesting is that modifying the Book model as described above does not make any changes to your table structures in your database. They remain unchanged. It's simply a matter of unlocking the api.

查看更多
登录 后发表回答