-1

我正在编写一个注册表单,只需要接受所需电子邮件地址的本地组件。域组件固定到站点。我试图通过有选择地复制validators.validate_emailDjango 提供的内容来验证它EmailField

email_re = re.compile(
    r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*"  # dot-atom
    # quoted-string, see also http://tools.ietf.org/html/rfc2822#section-3.2.5
    r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*"'
    r')@((?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?$)'  # domain
    r'|\[(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\]$', re.IGNORECASE)  # literal form, ipv4 address (SMTP 4.1.3)
validate_email = EmailValidator(email_re, _(u'Enter a valid e-mail address.'), 'invalid')

以下是我的代码。我的主要问题是我无法调整正则表达式。在这一点上,我只是在http://www.pythonregex.com/的正则表达式测试器中对其进行测试,但是它失败了:

^([-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*)$

这似乎传递了不受欢迎的字符,例如?

我的领域的整个代码,在这个阶段不一定相关,但我不介意对此发表评论:

class LocalEmailField(CharField):    
    email_local_re = re.compile(r"^([-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*)$", re.IGNORECASE)
    validate_email_local = RegexValidator(email_re, (u'Enter a valid e-mail username.'), 'invalid')
    default_validators = [validate_email_local]

编辑:为了澄清,用户只在 之前输入文本@,因此我不需要在验证@domain.com器中验证 。

编辑 2:所以表单字段和标签将如下所示:

所需的电子邮件地址:[---可输入区域---]@domain.com

4

4 回答 4

2

您说“诸如“之类的不受欢迎的字符?,但我认为您误解了哪些字符是可取的。原始的正则表达式允许问号。

请注意,您还可以定义自己的不使用大量正则表达式的验证器,并有机会稍后解码逻辑。

于 2012-09-10T05:06:20.480 回答
1

有些人在遇到问题时会想,“我知道,我会使用正则表达式。” 现在他们有两个问题。-杰米扎温斯基

通过正则表达式检查是一种浪费时间的练习。最好的方法是尝试交付;这样不仅可以验证电子邮件地址,还可以验证邮箱是否实际处于活动状态并且可以接收电子邮件。

否则,你最终会得到一个不可能匹配所有规则的不断扩展的正则表达式。

"Haha boo hoo woo woo!"@foo.com是一个有效的地址,所以是qwerterukeriouo@gmail.com

相反,提供几乎标准的“请单击我们发送到 blahblah@goo.com 的电子邮件中的链接以验证您的地址。” 方法。

如果您想创建电子邮件地址,那么您可以编写自己的规则来定义电子邮件组件的一部分;它们可以是 RFC 中官方允许的字符的子集。

例如,一个保守的规则(不使用正则表达式):

allowed_chars = [string.digits+string.letters+'-']

if len([x in user_input if x not in allowed_chars]):
   print 'Sorry, invalid characters'
else:
   if user_input[0] in string.digits+'-':
      print 'Cannot start with a number or `-`'
   else:
      if check_if_already_exists(user_input):
         print 'Sorry, already taken'
      else:
         print 'Congratulations!'

      
于 2012-09-10T05:04:30.840 回答
1

我对 Django 和 Python 还很陌生,但为什么要重新发明轮子并维护自己的正则表达式呢?如果除了希望用户只输入他们电子邮件地址的本地部分之外,您对 Django 的内置部分感到满意EmailField​​,您可以很容易地对其进行子类化并稍微调整验证逻辑:

DOMAIN_NAME = u'foo.com'


class LocalEmailField(models.EmailField):
    def clean(local_part):
        whole_address = '%s@%s' % (local_part, DOMAIN_NAME)
        clean_address = super(LocalEmailField, self).clean(whole_address)
        # Can do more checking here if necessary
        clean_local, at_sign, clean_domain = clean_address.rpartition('@')
        return clean_local

您是否查看过表单和字段验证以及.clean() 方法的文档?

于 2012-09-10T05:56:38.237 回答
0

如果你想用正则表达式 100% 正确地做到这一点,你需要使用带有某种形式的扩展正则表达式的引擎,它允许匹配嵌套的括号。

Python 的默认引擎不允许这样做,因此最好使用一个非常简单(许可)的正则表达式。

于 2012-09-10T05:15:44.500 回答