防止模型中的条目将自身添加到多对多关系中

Prevent an entry in model from adding itself in many2many relationship

我想阻止用户在 Django 中关注自己。用户模型定义如下:

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

更改用户模型中的 save() 方法没有帮助,因为 add() 方法不调用 save()。似乎是使用 m2m_changedUniqueConstraint 的解决方案,但我不知道如何实现它们。我该如何解决这个问题?

UniqueConstraint 将无济于事,因为这只会强制您不要关注同一个用户两次。

你可以做的是构造一个through=… model [Django-doc],并强制follower和followee不一样:

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,
        <b>through='Follow'</b>,
        <b>through_fields=('followee', 'follower')</b>,
    )

Follow 模型中,我们强制要求 followerfollowee 不能相同:

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(<b>check=~Q(follower=F('followee'))</b>, name='not_follow_self')
        ]

但并非所有数据库都强制执行 CheckConstraint。因此,最好也实施 clean 方法。