[Fixed]-Django model: Email field unique if not null/blank

24👍

Unfortunately, it’s not as simple as just setting null=True, unique=True, blank=True. Whenever you try to import using csv, or some other text based source, some part of Django, for the purpose of uniqueness treats “” as something that ought not to be duplicated.

The work-around, is to overwrite the save method, as follows:

def save(self, *args, **kwargs):
    # ... other things not important here
    self.email = self.email.lower().strip() # Hopefully reduces junk to ""
    if self.email != "": # If it's not blank
        if not email_re.match(self.email) # If it's not an email address
            raise ValidationError(u'%s is not an email address, dummy!' % self.email)
    if self.email == "":
        self.email = None
    super(Contact, self).save(*args, **kwargs)

Then,using unique, null and blank will work as intended.

Class Contact(models.Model):
    email = models.EmailField(max_length=70,blank=True, null= True, unique= True)

10👍

Just do this:

class Contact(models.Model):
    email = models.EmailField(max_length=70, null=True, blank=True, unique=True)

7👍

I tried to use the save but that still didn’t work because errors are already raised in the clean method, so I overwrote that instead for my model, it looks something like this:

Class MyModel(models.Model):
    email = models.EmailField(max_length=70,blank=True)
    first = models.CharField(max_length=25,blank=True)
    last = models.CharField(max_length=25,blank=True)
    phase_id = models.CharField('The Phase', max_length=255, null=True, blank=True, unique=True)

    ...

    def clean(self):
        """
        Clean up blank fields to null
        """
        if self.phase_id == "":
            self.phase_id = None

This works great for me, and the answer using the save may work for some cases, this one here should work by resetting the “” to None before the rest of the validation takes place in the base class clean. Cheers 🙂

👤radtek

1👍

Allow the CharField to null and default it to None. As long as you don’t have multiple blank field (“””), no integrity error will be raised.

#models.py
Class Contact(models.Model):
    email = models.EmailField(max_length=70, blank=True, null=True, unique=True, default=None)
# protect the db from saving any blank fields (from admin or your app form)
def save(self, *args, **kwargs):
    if self.email is not None and self.email.strip() == "":
        self.email = None
    models.Model.save(self, *args, **kwargs)

Leave a comment