17

假设您有一个简单的模型:

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)

我想做的是将电子邮件设置为唯一的,但是,这样做我必须排除空白电子邮件地址 - 我不希望这样。

我正在考虑这样的事情,但我想知道是否有更好的方法来处理它。

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)

有一个更好的方法吗?

4

4 回答 4

24

不幸的是,它并不像设置 null=True、unique=True、blank=True 那样简单。每当您尝试使用 csv 或其他基于文本的源进行导入时,Django 的某些部分出于唯一性的目的将“”视为不应重复的内容。

解决方法是覆盖保存方法,如下所示:

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)

然后,使用 unique、null 和 blank 将按预期工作。

Class Contact(models.Model):
    email = models.EmailField(max_length=70,blank=True, null= True, unique= True)
于 2013-03-20T20:54:46.037 回答
10

只需这样做:

class Contact(models.Model):
    email = models.EmailField(max_length=70, null=True, blank=True, unique=True)
于 2013-03-15T00:38:26.623 回答
7

我尝试使用 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

这对我很有用,并且使用保存的答案可能适用于某些情况,这里应该通过将“”重置为 None 来工作,然后在基类 clean 中进行其余的验证。干杯:)

于 2014-11-19T16:25:42.933 回答
1

允许 CharField 为空并将其默认为无。只要您没有多个空白字段(“”),就不会引发完整性错误。

#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)
于 2016-01-18T16:14:59.850 回答