Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to have validators with parameters?

Tags:

django

I can't find any relevant answer about this subject. I would like to create validators in Django with some parameters like:

In a forms.py file:

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

In a validators.py file:

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

I now I can do it via the clean method or doing a custom field but I think it would be nicer to do it via a validator. Is it possible?

Thanks in advance

like image 406
sandrob Avatar asked Aug 03 '12 16:08

sandrob


3 Answers

You could try writing a function which returns a function.

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

You could then create the validator you actually want by calling this function:

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

(thanks for the correction @user2577922)

PS I've not tested this, but hopefully you get the idea - write a function which takes the two dates you want to have as the bounds of your range, and which returns a function which checks that a date it is passed is in the range.

like image 96
Duncan Parkes Avatar answered Oct 20 '22 00:10

Duncan Parkes


I would suggest to take a look at django.core.validators to see how Django uses the Regex validator, and extends it to use for different type of fields.

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

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

Simply pass your parameters to the validator in

validators=[MyValidator(params)]

Haven't tested but I don't see any reason why it wouldn't work.

EDIT:

Had a chance to test it and it works.

like image 14
amertkara Avatar answered Oct 20 '22 01:10

amertkara


Based on amertkara's solution, I pass user's email address to the form, then I validate the user input agaist his own email address.

# 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
like image 4
s.benve Avatar answered Oct 19 '22 23:10

s.benve