Django - отключить создание объекта Invitation, если объект User с email существует
Я хотел бы убедиться, что никто не может создать объект Invitation
с email, который уже есть в базе данных либо как Invitation.email
, либо как User.email
.
Запретить создавать Invitation
с существующими Invitation.email
просто:
class Invitation(..):
email = ...unique=True)
Возможно ли также проверить наличие email в таблице User
? Я хочу сделать это на уровне базы данных или модели вместо того, чтобы проверять его в сериализаторе, формах и т.д.
Я думал о UniqueConstraint
, но не знаю, как сделать так, чтобы User.objects.filter(email=email).exists()
искал там.
Как насчет переопределения метода сохранения?
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)
Вы можете сделать это в модели... как показано ниже. Или вы можете сделать это в базе данных с помощью Check Constraint (предполагается, что 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
не имеет возвращаемого значения. Причина этого в том, что я никогда не предполагаю, что аргументы или возвращаемое значение метода, который я переопределяю, не изменятся в будущем. Передавать их все, если у вас нет причин перехватывать их, - это просто хорошая практика.
Вы можете переопределить метод 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)