是否可以使用带参数的验证器?

时间:2012-08-03 16:31:57

标签: django

我找不到关于这个主题的任何相关答案。 我想在Django中使用一些参数创建验证器:

在forms.py文件中:

class DateForm(forms.Form):
    forms.DateField(
        validators=[validate_range_of_date(value,"01/06/2012","31/03/2013")]
        )

在validators.py文件中:

def validate_range_of_date(date_to_verify, min_date, max_date):
    ...

我现在可以通过clean方法或自定义字段来实现,但我认为通过验证器进行此操作会更好。有可能吗?

提前致谢

5 个答案:

答案 0 :(得分:11)

您可以尝试编写一个返回函数的函数。

def date_range_validator(min_date, max_date):
    def innerfn(date_to_test):
        if not (min_date <= date_to_test <= max_date):
            raise ValidationError(
                'Inappropriate date: %s is not between %s and %s' %
                (date_to_test, min_date, max_date)
                )
    return innerfn

然后,您可以通过调用此函数来创建您真正想要的验证器:

class DateForm(forms.Form):
    forms.DateField(
        validators=[
            date_range_validator(
                datetime.date(2012, 06, 01), datetime.date(2013, 03, 31)
                )
            ]
        )

(感谢更正@user2577922

PS我没有测试过这个,但希望你能得到这个想法 - 编写一个需要的功能 您希望拥有的两个日期作为范围的范围,并返回一个函数 检查传递的日期是否在范围内。

答案 1 :(得分:7)

我建议查看django.core.validators以了解Django如何使用Regex验证器,并将其扩展为用于不同类型的字段。

class MyValidator (object):
    def __init__(self, params):
        pass  #  Init the instance variables here

    def __call__(self, value):
        pass  # Actual validation logic comes here

只需将参数传递给

中的验证器即可
validators=[MyValidator(params)]

没有经过测试,但我认为没有任何理由说它不起作用。

编辑:

有机会测试它并且有效。

答案 2 :(得分:3)

根据amertkara的解决方案,我将用户的电子邮件地址传递给表单,然后我验证用户输入是否为他自己的电子邮件地址。

# form
class new_user_form(forms.Form):
    def __init__(self, *args, **kwargs):
        own_mail = kwargs.pop('own_mail')
        super(new_user_form, self).__init__(*args, **kwargs)
        self.fields['email'] = forms.EmailField(
            label='',
            required=True,
            validators = [ not_own_mail(own_mail) ]
        )

# validator
class not_own_mail(object):
    def __init__(self, email):
        self.email = email

    def __call__(self, value):
       if value == self.email:
            raise ValidationError('It must be a different email address.')
       else:
           return value

答案 3 :(得分:1)

您可以构建一个验证器,以 builtin validators 为例,不要忘记在类上使用可解构的装饰器。

@deconstructible
class ValidateStartsWith(object):
    def __init__(self, prefix: str):
        self.prefix = prefix

    def __call__(self, value: str):
        value = value.strip()
        if value.startswith(self.prefix):
            if value == self.prefix:
                raise ValidationError(
                    f'El nombre debe incluir el prefijo "{self.prefix}" y algo más'
                )
        else:
            raise ValidationError(
                f'La convención del nombre exige que empieze con el prefijo "{self.prefix}"'
            )

答案 4 :(得分:0)

你可以尝试使用lambda表达式(从未尝试过,所以我不知道它是否会起作用):

forms.DateField(validators=[lambda value: validate_range_of_data(value, "01/06/2012", "31/03/2012")])

当然,你必须问问自己,这是否比在该领域的干净方法中验证更“好”。