I want to prevent a 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()
method 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?
A UniqueConstraint
will not help since this will only enforce that you do not follow the same user twice.
What you can do is construct a through=…
model [Django-doc], and enforce that the follower and the followee are not the same:
from django.conf import settings
from django.core.exceptions import ValidationError
from django.db import models
from django.db.models import F, Q
class User(AbstractUser):
# …
followers = models.ManyToManyField(
'self',
related_name='following',
symmetrical=False,
through='Follow',
through_fields=('followee', 'follower'),
)
In the Follow
model we then enforce that follower
and followee
can not be the same:
class Follow(models.Model):
followee = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name='followee_set'
)
follower = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name='following_set'
)
def clean(self, *args, **kwargs):
if self.follower_id == self.followee_id:
raise ValidationError('Can not follow self.')
return super().clean(*args, **kwargs)
class Meta:
constraints = [
models.UniqueConstraint(fields=['follower', 'followee'], name='follow_once'),
models.CheckConstraint(check=~Q(follower=F('followee')), name='not_follow_self')
]
Not all databases however enforce the CheckConstraint
. Therefore it might be better to implement a clean
method as well.