我想确保没有人可以创建一个Invitation
对象的电子邮件,已经在数据库中作为Invitation.email
或User.email
。
不允许在已有的Invitation.email
上创建Invitation
:
class Invitation(..):
email = ...unique=True)
是否也可以检查User
表中的邮件?我想在数据库或模型级别上执行此操作,而不是在序列化器,表单等中检查。
我正在考虑UniqueConstraint
,但我不知道如何使User.objects.filter(email=email).exists()
查找那里。
您可以覆盖模型上的save()方法,并首先在users表中进行检查。你应该看看,那是一种新型号。我想大概是这样的:
class Invitation(..):
email = ...unique=True)
def save(self, *args, **kwargs):
if self.id is None and User.objects.filter(email=self.email).exists():
raise ValidationError('Email already used.')
else:
super().save(*args, **kwargs)
您可以在模型中这样做。如下。或者您可以在数据库中使用检查约束(假设postgres)。但是您仍然无法避免向视图中添加代码,因为您需要捕获异常并向用户显示消息。
class Invitation(models.Model):
def save(self, *args, **kwargs):
if (not self.pk) and User.objects.filter(email=self.email).exists():
raise ValueError('Cannot create invitation for existing user %s.' % self.email)
return super().save(*args, **kwargs)
PS:有些人可能会问为什么我传递*args
和**kwargs
到超类,或返回返回值。当save
没有返回值时。这样做的原因是,我从不假设我重写的方法的参数或返回值在将来不会改变。如果你没有理由拦截它们,让它们全部通过,这是一个很好的做法。
如何重写保存方法?
class Invitation(...):
...
def save(self, *args, **kwargs):
# check if an invitation email on the user table:
if User.objects.get(id=<the-id>).email:
# raise integrity error:
...
# otherwise save as normal:
else:
super().save(*args, **kwargs)