防止模型中的条目将自身添加到多对多关系中
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_changed
或 UniqueConstraint
的解决方案,但我不知道如何实现它们。我该如何解决这个问题?
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
模型中,我们强制要求 follower
和 followee
不能相同:
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
方法。
我想阻止用户在 Django 中关注自己。用户模型定义如下:
class User(AbstractUser):
followers = models.ManyToManyField(‘self’, related_name=“following”, symmetrical= False)
更改用户模型中的 save()
方法没有帮助,因为 add()
方法不调用 save()
。似乎是使用 m2m_changed
或 UniqueConstraint
的解决方案,但我不知道如何实现它们。我该如何解决这个问题?
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
模型中,我们强制要求 follower
和 followee
不能相同:
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
方法。