Python Django 模型:电子邮件字段如果不是空/空白则是唯一的
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15422606/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Django model: Email field unique if not null/blank
提问by Brandon Bertelsen
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?
有一个更好的方法吗?
采纳答案by Brandon Bertelsen
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.
不幸的是,这并不像设置 null=True、unique=True、blank=True 那样简单。每当您尝试使用 csv 或其他一些基于文本的源进行导入时,Django 的某些部分出于唯一性目的将 "" 视为不应重复的内容。
The work-around, is to overwrite the save method, as follows:
解决方法是覆盖 save 方法,如下所示:
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.
然后,使用 unique、null 和 blank 将按预期工作。
Class Contact(models.Model):
email = models.EmailField(max_length=70,blank=True, null= True, unique= True)
回答by Fernando Freitas Alves
Just do this:
只需这样做:
class Contact(models.Model):
email = models.EmailField(max_length=70, null=True, blank=True, unique=True)
回答by radtek
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:
我尝试使用 save ,但仍然没有用,因为在 clean 方法中已经出现了错误,所以我改写了我的模型,它看起来像这样:
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 :)
这对我很有用,并且使用 save 的答案可能适用于某些情况,这里的这个应该通过在基类 clean 中进行其余验证之前将 "" 重置为 None 来工作。干杯:)
回答by user3526918
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.
允许 CharField 为 null 并将其默认为 None。只要您没有多个空白字段 ("""),就不会引发完整性错误。
#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)

