[Django]-Why can't uniqueness be enforced on Django ManyToMany field?

4👍

Consider using a ManyToMany through table.

class Summary(models.Model):
    user_ratings = models.ManyToManyField(
        'User', blank=True, through='UserRating',
    )


class UserRating(models.Model):
    user = models.ForeignKey('User')
    summary = models.ForeignKey('Summary')
    is_positive = models.BooleanField()

    class Meta:
        unique_together = ('user', 'summary')

Then you can query users who reviewed the summary positively with something like

summary.user_ratings.filter(is_positive=True)
summary.user_ratings.filter(is_positive=False)

The unique_together property ensures that a user can’t review the same summary twice.

You could even retain similar syntax using a custom queryset. Here’s a guess at what that might look like:

class SummaryQuerySet(models.QuerySet):

    def users_rated_negative(self):
        return self.user_ratings.filter(is_positive=False)

    def users_rated_positive(self):
        return self.user_ratings.filter(is_positive=True)


class Summary(models.Model):
    user_ratings = models.ManyToManyField(
        'User', blank=True, through='UserRating',
    )

    objects = SummaryQuerySet.as_manager()

Now the in-use syntax is summary.users_rated_positive

A similar custom queryset for User would give you the summaries_rated_positive property, if you needed that too.

Leave a comment