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.
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.
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)