我有以下表格:
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(),
}
当我不使用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())
但是SplitDateTimeWidget
用于DateTime
字段时,测试不再运行。他们抛出错误而非失败,特别是:
AttributeError: 'NoneType' object has no attribute 'date'
在我的重写形式a1
方法中访问clean
变量时。
我查看了相关的源代码,并且无法理解为什么使用SelectDateTimeWidget
会在命令行或测试中需要不同的输入,但显然它确实如此。我的测试应该如何以clean
方法能够访问的方式提供数据?
编辑:
从渲染的html中提取我的提示我还尝试从date_and_time_of_first_appointment_0
和date_and_time_of_first_appointment_1
这样的字段中获取单独的日期和时间,并在clean
方法中进行比较之前将它们组合起来但无济于事。< / p>
答案 0 :(得分:0)
我解决了这个问题。渲染的HTML确实告诉我该怎么做,但我把我的解决方案放在了错误的地方。
而不是在clean方法中查找单独的字段,这是我最初尝试过的,您需要将它们放在测试数据中。 Django会在数据传递到clean()
之前将它们组合在一起。我的测试现在看起来像:
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_0': timezone.now().date(),
'date_and_time_of_first_appointment_1': timezone.now().time(),
'date_and_time_final_appointment_finishes_0': timezone.now().date(),
'date_and_time_final_appointment_finishes_1': timezone.now().time(),
'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())
一切都过去了。