Django 1.5 SplitDateTimeWidget向form.clean()发送了什么数据?

时间:2014-02-06 16:13:00

标签: django django-forms django-crispy-forms

我有以下表格:

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_0date_and_time_of_first_appointment_1这样的字段中获取单独的日期和时间,并在clean方法中进行比较之前将它们组合起来但无济于事。< / p>

1 个答案:

答案 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())

一切都过去了。