Prevent an entry in model from adding itself in many2many relationship

I want to prevent an user from following themselves in django. The User model is defined like bellow:

class User(AbstractUser):
followers = models.ManyToManyField(‘self’, related_name=“following”, symmetrical= False)

Changing save() method in the User model doesn’t help since add doesn’t call save(). The seems to be a solution using m2m_changed or UniqueConstraint but I don’t know how to implement them. How can I solve this problem?

You want to add a custom through model, and then place a CheckConstraint on the through model that the “from” and “to” FK’s are not equal. Something like this (untested):

class FollowRelationship(models.Model):
    from = models.ForeignKey(User, on_delete=models.CASCADE)
    to = models.ForeignKey(User, on_delete=models.CASCADE)
    
    class Meta:
        constraints = [
            models.UniqueConstraint(
                name="%(app_label)s_%(class)s_unique_relationships",
                fields=["from", "to"]
            ),
            models.CheckConstraint(
                name="%(app_label)s_%(class)s_prevent_self_follow",
                check=~models.Q(from=F("to")),
            ),
        ]
        

class User(models.Model):
    followers = models.ManyToManyField('self', through=FollowRelationship, ...)

For a fully fleshed out and tested example of using and testing a check constraint see my post: Using Django Check Constraints to Limit A Model to a Single Instance - Adam Johnson

This example is a good candidate for me to write another post on :slight_smile:

I wrote a post: Using Django Check Constraints to Prevent Self-Following - Adam Johnson

2 Likes