I have the following form:
class TripForm(IntranetForm):
def __init__(self, *args, **kwargs):
super(TripForm, self).__init__(*args, **kwargs)
self.helper.layout = Layout(
Field('reason', css_class='input-xlarge'),
Field('departure_date'),
Field('return_date'),
Field(
'date_and_time_of_first_appointment',
),
Field(
'date_and_time_final_appointment_finishes',
),
Field(
'departure_location',
template='travel/related_departure.html',
),
Field(
'destination',
template='travel/related_destination.html',
),
Field('mode_of_transport', css_class='input-xlarge'),
Field('seating_preference', css_class='input-xlarge'),
Field('special_requests', css_class='input-xlarge'),
FormActions(
Submit(
'save_changes',
'Save changes',
css_class = "btn-primary",
),
Button(
'cancel',
'Cancel',
onclick = 'history.go(-1);'
),
),
)
def clean(self):
cleaned_data = super(TripForm, self).clean()
departure_date = cleaned_data.get("departure_date")
return_date = cleaned_data.get("return_date")
a1 = cleaned_data.get("date_and_time_of_first_appointment")
af = cleaned_data.get("date_and_time_final_appointment_finishes")
if departure_date < datetime.date.today():
msg = u"Must be a date in the future."
self._errors["departure_date"] = self.error_class([msg])
del cleaned_data["departure_date"]
if a1.date() < departure_date:
msg = u"Must be after the departure date."
self._errors["date_and_time_of_first_appointment"] = self.error_class([msg])
del cleaned_data["date_and_time_of_first_appointment"]
if return_date < departure_date:
msg = u"Must be after the departure date."
self._errors["return_date"] = self.error_class([msg])
del cleaned_data["return_date"]
if af < a1 or af.date() > return_date:
msg = u"Must be after the first appointment and before the return date."
self._errors["date_and_time_final_appointment_finishes"] = self.error_class([msg])
del cleaned_data["date_and_time_final_appointment_finishes"]
return cleaned_data
class Meta:
model = Trip
fields = (
'reason',
'departure_date',
'return_date',
'date_and_time_of_first_appointment',
'date_and_time_final_appointment_finishes',
'departure_location',
'destination',
'mode_of_transport',
'seating_preference',
'special_requests',
)
widgets = {
'date_and_time_of_first_appointment': SplitDateTimeWidget(),
'date_and_time_final_appointment_finishes': SplitDateTimeWidget(),
}
Tests similar to the one below all work fine when I don't use the SplitDateTimeWidget
.
def test_trip_form_with_good_data(self):
form_data = {
'reason': 'HE',
'departure_date': timezone.datetime.today(),
'return_date': timezone.datetime.today(),
'date_and_time_of_first_appointment': timezone.now(),
'date_and_time_final_appointment_finishes': timezone.now(),
'departure_location': 1,
'destination': 1,
'mode_of_transport': 'TR',
'seating_preference': 'Near the front',
'special_requests': 'Make it nice',
}
form = TripForm(data=form_data)
self.assertTrue(form.is_valid())
But the tests no longer run when the SplitDateTimeWidget
is being used for the DateTime
fields. They throw errors rather than failing, specifically:
AttributeError: 'NoneType' object has no attribute 'date'
whenever the a1
variable is accessed in my overridden form clean
method.
I've looked at the relevant source code and couldn't see why using the SelectDateTimeWidget
would necessitate different input at the command line or in tests, but clearly it does. How should my tests provide data in a way that the form clean
method will be able to access?
EDIT:
Taking my cue from the rendered html I've also tried getting separate dates and times from fields like date_and_time_of_first_appointment_0
and date_and_time_of_first_appointment_1
and combining them before comparison in the clean
method but to no avail.