Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django model: Email field unique if not null/blank

Tags:

python

django

Let's say you have a simple model:

Class Contact(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)

What I would like to do is set email to be unique, however, in doing so I necessarily make it such that I exclude blank email addresses - and I don't want that.

I was thinking about something like this but I'm wondering if there is a better way to deal with it.

from django.core.validators import email_re
from django.core.exceptions import ValidationError

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 Contact.objects.filter(email = self.email) # If it already exists
            raise ValidationError(u'%s already exists in database, jerk' % self.email) 
    super(Contact, self).save(*args, **kwargs)

Is there a better way to do this?

like image 640
Brandon Bertelsen Avatar asked Mar 15 '13 00:03

Brandon Bertelsen


People also ask

Can a unique field be NULL Django?

In all of Django's supported DMBSes, the UNIQUE constraint does not apply to NULL values. This allows the database to represent data of the form "This must be unique where it is set".

What is difference between NULL and blank in Django?

In Very simple words, Blank is different than null. null is purely database-related, whereas blank is validation-related(required in form). If null=True , Django will store empty values as NULL in the database . If a field has blank=True , form validation will allow entry of an empty value .

How does Django handle NULL value?

If a string-based field has null=True , that means it has two possible values for “no data”: NULL, and the empty string. In most cases, it's redundant to have two possible values for “no data;” the Django convention is to use the empty string, not NULL.

What is unique together in Django?

Django unique_together is used to make two or more model fields to be unique. class MyModel(models.Model): field1 = models.CharField(max_length=50) field2 = models.CharField(max_length=50) field3 = models.CharField(max_length=50) class Meta: unique_together = ('field1', 'field2',)


2 Answers

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)
like image 64
Brandon Bertelsen Avatar answered Oct 17 '22 23:10

Brandon Bertelsen


Just do this:

class Contact(models.Model):
    email = models.EmailField(max_length=70, null=True, blank=True, unique=True)
like image 39
Fernando Freitas Alves Avatar answered Oct 18 '22 00:10

Fernando Freitas Alves