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

问题描述

我想阻止用户在 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 方法。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...