Какие данные Django 1.5 SplitDateTimeWidget отправляет в form.clean()?

У меня есть следующая форма:

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 метод, но безрезультатно.

1 ответ

Решение

Я решил это. Рендеринг HTML действительно говорил мне, что делать, но я поставил свое решение не в том месте.

Вместо того, чтобы искать отдельные поля в чистом методе, что я и пытался изначально, вам нужно поместить их в свои тестовые данные. 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())

И все снова проходит.

Другие вопросы по тегам