【问题标题】:Django EmailField accepts invalid valuesDjango EmailField 接受无效值
【发布时间】:2013-08-21 21:42:20
【问题描述】:

我目前在表单上使用默认的EmailField 属性。我遇到的问题是表单认为name@mail.56 等无效电子邮件是有效的。我是否需要在此字段上实现自己的validators 才能使其正常工作?

我的印象是:

#models.py
email = models.EmailField(max_length=254, blank=False, unique=True,
        error_messages={'required': 'Please provide your email address.',
                        'unique': 'An account with this email exist.'},)

或者有:

#forms.py
email = forms.EmailField()

将为我处理此类验证,但似乎并非如此。

【问题讨论】:

    标签: django django-forms


    【解决方案1】:

    确实,name@mail.56 电子邮件是 django EmailValidator 的有效电子邮件,看不到错误:

    >>> from django.core.validators import validate_email
    >>> validate_email("name@mail.56")
    >>>
    

    Django (1.5.1) 使用以下正则表达式来验证电子邮件地址:

    r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*"  # dot-atom
        # quoted-string, see also https://www.rfc-editor.org/rfc/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}\.?|[A-Z0-9-]{2,}\.?)$)'  # 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}\]$'
    

    它实际上遵循RFC2822 标准。

    如果您想让name@mail.56在验证过程中失败,您可以创建自己的验证器,并将其添加到带有内置validate_email验证器的EmailField验证器中,如下所示:

    from django.core.validators import validate_email
    from django.core.exceptions import ValidationError
    
    def custom_validate_email(value):
        if <custom_check>:
            raise ValidationError('Email format is incorrect')
    ...
    email = models.EmailField(max_length=254, blank=False, unique=True, validators=[validate_email, custom_validate_email)
    

    而且,仅供参考,您可以随时在 django ticket system 提交工单或在 django IRC 频道 (irc://irc.freenode.net/django) 上询问问题。

    另请参阅:Writing validators

    希望对您有所帮助。

    【讨论】:

      【解决方案2】:

      你可以看到使用的正则表达式here

      我认为它不会 100% 丢弃错误的电子邮件。这就是为什么在docs 中它说:

      验证给定的值是一个有效的电子邮件地址,使用 中等复杂的正则表达式。

      我从中了解到的是,由于设计决策,它并没有进行完美的验证(这将是一个性能权衡)。

      最后,我很确定您的示例 name@mail.56 是有效的电子邮件。电子邮件地址的域部分可以是 IP(IPv4 和 IPv6)或主机名。有关该主题的更多信息,请参阅here

      【讨论】:

        【解决方案3】:

        对于仅数据库级别的验证,您必须手动调用 full_clean

        文档中的三个重要引用:

        How validators are run

        有关验证器如何运行的更多信息,请参阅表单验证 在表单中,以及验证对象如何在模型中运行。笔记 保存模型时验证器不会自动运行, 但如果您使用的是 ModelForm,它将在任何 表单中包含的字段。请参阅 ModelForm 文档 有关模型验证如何与表单交互的信息。

        Model.clean_fields

        full_clean() 执行的第二步是调用 Model.clean()。这个 方法应该被覆盖以对您的执行自定义验证 型号。

        Model.full_clean

        注意full_clean()在你调用的时候不会自动调用 你模型的 save() 方法。您需要手动调用它 想要为您自己手动创建的运行一步模型验证 模型。

        from django.db import models
        
        
        class MyTable(models.Model):
            email = models.EmailField(unique=True)
        
            def save(self, *args, **kwargs):
                super().full_clean()
                super().save(*args, **kwargs)
        

        【讨论】:

          猜你喜欢
          • 2015-01-13
          • 2015-05-21
          • 2013-11-09
          • 2015-01-18
          • 1970-01-01
          • 2020-06-08
          • 2017-01-31
          • 2016-01-03
          • 1970-01-01
          相关资源
          最近更新 更多