如何在Django 1.11中覆盖用户名验证?

时间:2017-08-18 12:44:19

标签: python django validation django-models django-registration

我的Django 1.11网站中有a custom user model以及django-registration

在我的注册表单上,我提示输入用户名和密码。我已将settingsLengthValidator和自定义WordCountValidator验证添加到settings.py中的密码短语字段(见下文) - 这些验证规则会自动在注册表单中呈现。

现在我想用三个规则更改用户名验证:length,必须以字母开头,可能只包含字母数字字符。我不介意将这些组合成一条规则。

我尝试将username_validator添加到该类并进行设置,但没有任何反应 - 可能是因为我继承自AbstractUser而非用户(related 1.10 bug?)

如何在我的用户名字段中使用自己的验证规则(最好是多子句)?

表单的简化外观:

Username: [     ]

Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.

Passphrase: [     ]

Your passphrase must contain at least 15 characters.
Passphrase must contain at least three words. Use spaces between words.

Passphrase confirmation: [       ]

Enter the same passphrase as before, for verification.

settings.py

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
        'OPTIONS': {
            'min_length': 15,
        }
    },
    {
        'NAME': 'custom.validators.WordCountValidator',
        'OPTIONS': {
            'min_words': 3,
        }
    },
]

models.py

class User(AbstractUser):
    objects = UserManager()

    def __init__(self, *args, **kwargs):

        user = super(User, self).__init__(*args, **kwargs)
        return user

    ...

validators.py

class WordCountValidator(object):
    ...

class StartLetterValidator(object):
    ...

class AlphanumericValidator(object):
    ...

class CombinedValidator(object):
    ...

1 个答案:

答案 0 :(得分:1)

覆盖clean()模型的User方法并在那里调用验证器:

def clean(self):
    # do some data-clean
    # maybe do a super().clean() here

    validator1 = WordCounterValidator(self)
    validator1.myValidationMethod()
    #...
    validator2 = StartLetterValidator(self)
    validator2.myValidationMethod()
    #...
    validator3 = AlphanumericValidator(self)
    validator3.myValidationMethod()
    #...
    validator4 = CombinedValidator(self)
    validator4.myValidationMethod()
    #...

    # maybe do a super().clean() here

为了简化验证代码,编写验证方法而不是验证类可能很有用。但我认为这两种设计都可以。

更新

由于答案的大小,评论中的问题得到了扩展答案:

django为此提供了ValidationError。如果您想一次提出多个ValidationError,我建议您使用字典来收集错误:

err_dict = {}

然后只需将 field-name 作为键,并将错误消息作为值err_dict["field-name"] = "Error mssg"添加到该dict的错误:

clean()结束时,只需检查您的dict是否有if err_dict的错误(如果dict中出现错误[s],则为true),并使用raise ValidationError(err_dict)提出错误。

在您的情况下,您可能想要执行类似

的操作
err_dict = validatot1.myValidationMethod(err_dict)

使用每个验证功能扩展您的err_dict(如有必要)。