Почему form.is_valid () не возвращает false сразу, когда первый clean_ поднимает ValidationError? - PullRequest
0 голосов
/ 23 апреля 2020

Я определил форму с двумя CharField. Я определил чистый метод для обоих полей. На мой взгляд, я вызываю метод is_valid() формы, которую я определил. Я даю неверный ввод для field1, так что метод clean_field1 повышает ValidationError.

В clean_field2 У меня есть доступ cleaned_data[field1]. При вызове URL выдается ошибка 500. И в трассировке стека это говорит KeyError: 'field1' . При отладке я обнаружил, что ValidationError был поднят в методе clean_field1.

Я ожидал, что Form.is_valid() вернет false, когда clean_field1 поднял ValidationError. Но django продолжал выполнять clean_field2. Почему django выполняет clean_field2, когда clean_field1 поднял ValidationError. form.is_valid() должен был вернуть False, когда clean_field1 поднял ValidationError. Я прав?

Возвращает ли метод form.is_valid() только после выполнения всех методов clean_<'field_name'> (даже если ValidationError было поднято)? Если да, то этот плохой дизайн мне кажется. Если первый метод clean_<'field_name'> поднимает ValidationError, то какой смысл в выполнении другого метода clean_<'field_name'>? Я думаю, Form.is_valid() должен вернуть False, когда он впервые встретит ValidationError. Или я что-то упустил?

Будет ли полезно, если кто-нибудь сможет объяснить, что происходит? Спасибо.

Код, который я выполнял:

class MyForm(Form):
    field1 = forms.CharField()
    field2 = forms.CharField()
    def clean_field1(self):
        clean_field1 = self.cleaned_data['field1']
        if not check_validity(clean_field1):
            raise ValidationError(_('Invalid Field1 input'), code='invalid_field1_input')
        return clean_field1

    def clean_field2(self):
        clean_field2 = self.cleaned_data['field2']
        my_query_set = MyTable.objects.filter(my_field__exact=self.cleaned_data['field1'])
        if not my_query_set.exists():
            raise ValidationError(_('Some Error'), code='some_error_code')
        return clean_field2

class MyView(View):
    def post(self, request):
        response_data={'status':'fail'}
        json_data = json.loads(request.body)
        form = MyForm(json_data)
        if(form.is_valid()):
            #do something
            response_data['status']='success'
        else:
            response_data['errors']=form.errors
        return JsonResponse(response_data)

1 Ответ

2 голосов
/ 23 апреля 2020

Django проверяет все поля до определения достоверности формы в целом.

Это и намеренный, и умный дизайн. Причина в том, что это бесит быть пользователем и заполнять форму, а не получать полный отзыв о вашем представлении.

Например, если у вас было поле с 10 полями, а пользователь ввел 4 неправильных значения, это было бы больно, чтобы отправить форму 4 раза. Каждый раз при отправке формы обнаруживается, что новое поле недействительно.

Это утомительно для пользователя. Из-за этого Django проверяет все входные данные.

Вы можете прочитать о процессе проверки в Djanog Docs Прочитать абзац чуть выше заголовка "Raising ValidationError".

...