I'd like to make sure that nobody can't create an Invitation
object with an email that is already in a database either as Invitation.email
or as User.email
.
To disallow creating Invitation
with existing Invitation.email
is easy:
class Invitation(..):
email = ...unique=True)
Is it also possible to check for the email in User
table? I want to do this on a database or model level instead of checking it in serializer, forms etc..
I was thinking about UniqueConstraint
but I don't know how to make the User.objects.filter(email=email).exists()
lookup there.
CodePudding user response:
You can override the save() method on the model, and check first in the users table. You should look that is a new model. Something like this I think:
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)
CodePudding user response:
You can do it in the model.. as below. Or you can do it in the database with a Check Constraint (assuming postgres).. but you still can't avoid adding code to your view, because you'll need to catch the exception and display a message to the user.
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: Some may ask why it is that I am passing *args
and **kwargs
to the superclass, or returning the return value.. when save
has no return value. The reason for this is that I never assume that the arguments or return value for a method I am overriding won't change in the future. Passing them all through if you have no reason to intercept them, is just a good practice.
CodePudding user response:
How about overriding the save method?
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)