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?
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".
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 .
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.
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',)
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)
Just do this:
class Contact(models.Model):
email = models.EmailField(max_length=70, null=True, blank=True, unique=True)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With