21

Let us say I have a model for social network posts, users and likes:

class Post(models.Model):
    submitter = models.ForeignKey(User, null=False, default=None)
    content = models.CharField()
    date = models.DateField()

    with_likes = PostLikeCountManager()
    objects = models.Manager()

class Like(models.Model):
    user = models.ForeignKey(User)
    post = models.ForeignKey(Post)
    time = models.DateTimeField(auto_now_add=True)

It would be helpful to think of Post model as representing a Facebook post. Now, I would like to limit one like per post per user. How do I achieve that? One way would be to create a composite primary key on (user, post) attributes of Like class. I don't know how to achieve that in Django. The other would be to use unique=True on two attributes simultaneously. Is that possible?

Thanks.

abhinavkulkarni
  • 2,284
  • 4
  • 36
  • 54

2 Answers2

32

Yes, use unique_together:

class Like(models.Model):
    user = models.ForeignKey(User)
    post = models.ForeignKey(Post)
    time = models.DateTimeField(auto_now_add=True)

    class Meta:
        unique_together = ('user', 'post')
MichielB
  • 4,181
  • 1
  • 30
  • 39
knbk
  • 52,111
  • 9
  • 124
  • 122
19

unique_together will be deprecated in the future version, instead you could apply UniqueConstraint. This and this link gives example code.

class Like(models.Model):
    user = models.ForeignKey(User)
    post = models.ForeignKey(Post)
    time = models.DateTimeField(auto_now_add=True)

    class Meta:
        constraints = [
            models.UniqueConstraint(fields=['user', 'post'], name='unique_user_post'),
        ]
Ham
  • 703
  • 8
  • 17