Home > Software engineering >  django - disable Invitation object creation if User object with the email exists
django - disable Invitation object creation if User object with the email exists

Time:09-24

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)
  • Related