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

问题描述

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

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

更改 User 模型中的 save() 方法无济于事,因为 add() 方法不会调用 save()。这似乎是使用 m2m_changedUniqueConstraint解决方案,但我不知道如何实现它们。我该如何解决这个问题?

解决方法

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

您可以做的是构造一个 through=… model [Django-doc],并强制关注者和被关注者不同:

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'),)

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,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')
        ]

并非所有数据库都强制CheckConstraint。因此,最好也实现一个 clean 方法。