Django form validation using MaxValueValidator with dynamic values

Go To StackoverFlow.com

1

I have a form which takes a start date and end date as input.I need to set the valid range but this is dependent on another field, site. Like so:

class GraphForm(forms.Form):
    site = forms.ChoiceField(choices=SITE_CHOICES, label=ugettext_lazy('Site'),
                widget=forms.Select(attrs={"onChange":'filterField()'})
                )
    startdate = forms.DateField(
                label=ugettext_lazy('Start Date'),
                validators=[MaxValueValidator(maxdate)], 
                )
    enddate = forms.DateField(
                label=ugettext_lazy('End Date'),
                validators=[MaxValueValidator(maxdate)], 
                )
    ...

But I can get a value for maxdate only when a site has been selected:

getdate = Reports.objects.filter(site=site_name).values('recorded_on').order_by('-recorded_on')[:1]
maxdate = getdate[0]['recorded_on']

My question is how can I achieve this functionality - that I get the site input and then generate my maxdate value before the form can validate.

Any help much appreciated.

2012-04-05 21:45
by Darwin Tech


2

You can't do this in the field definitions, as each field is validated separately. However, you could write a custom clean method for your form which checks start date and end date for you.

2012-04-05 23:44
by Alasdair


1

You can write a dynamic validation class, i.e. a class that does not take a constant but a function that will be called during validation.

from django.core.validators import MaxValueValidator
from django.core.exceptions import ValidationError

class DynamicMaxValueValidator(MaxValueValidator):
    def __call__(self, value):
        cleaned = self.clean(value)
        params = {'limit_value': self.limit_value(), 'show_value': cleaned}
        if self.compare(cleaned, self.limit_value()):
            raise ValidationError(
                self.message % params,
                code=self.code,
                params=params,
                )

def maxdate():
    getdate = Reports.objects.filter(site=site_name).values('recorded_on').order_by('-recorded_on')[:1]
    return getdate[0]['recorded_on']

class GraphForm(forms.Form):
    site = forms.ChoiceField(choices=SITE_CHOICES, label=ugettext_lazy('Site'),
                widget=forms.Select(attrs={"onChange":'filterField()'})
                )
    startdate = forms.DateField(
                label=ugettext_lazy('Start Date'),
                validators=[DynamicMaxValueValidator(maxdate)], 
                )
    enddate = forms.DateField(
                label=ugettext_lazy('End Date'),
                validators=[DynamicMaxValueValidator(maxdate)], 
                )
    ...

Notice that you must not call the function during initialization (no paranthesis behind maxdate when creating the DynamicMaxValueValidator)

2014-02-10 23:37
by mir
Ads