Django 5 для начинающих

Прогресс по курсу:  9/1004

4.1 Формы в Django
5 из 16 шагов пройдено
0 из 48 баллов  получено

Проверка (валидация) данных

Теоретически пользователь может ввести в форму и отправить какие угодно данные. Однако не все данные бывают уместными или корректными. Например, в поле для возраста пользователь может ввести отрицательное или четырехзначное число, что вряд ли может считаться корректным возрастом. В Django для проверки корректности вводимых данных используется механизм валидации.

Основными элементами валидации являются правила, которые определяют параметры корректности вводимых данных. Например, для всех полей по умолчанию устанавливается обязательность ввода значения, а при генерации НТМL-кода для поля ввода задается атрибут required(обязательное поле). И когда мы попробуем отправить форму, если в какое-либо из ее полей не введено никакого значения, то получим соответствующее предупреждение.

Проверим это на примере:

from django import forms


class UserForm(forms.Form):
    name = forms.CharField(label='Имя', help_text='Введите свое имя')
    age = forms.IntegerField(label='Ваш возраст?', help_text='Введите свой возраст')
    reklama = forms.BooleanField(label='Coглacны получать рекламу?')

Если одно из полей в форме окажется незаполненным, то при нажатии на кнопку Отправить пользователь получит предупреждение об ошибке. Таким образом, чтобы отправить данные, пользователь должен будет обязательно
ввести какое-либо значение в незаполненное поле.

Однако это не всегда нужно, поскольку одни поля всегда должны быть заполнены, а другие - нет.

Предположим, что в нашем примере пользователь не желает получать рекламу. Однако он не сможет отправить данные до тех пор, пока не поставит флажок в поле Согласны получать рекламу.

Для того, чтобы сделать поле не обязательным, мы должны добавить required=False, рассмотрим на примере:

from django import forms


class UserForm(forms.Form):
    name = forms.CharField(label='Имя', initial='undefined', help_text='Введите свое имя')
    age = forms.IntegerField(label='Ваш возраст?', initial=18, help_text='Введите свой возраст')
    reklama = forms.BooleanField(label='Coглacны получать рекламу?', required=False)


И вернем наш шаблон в прежний вид:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Учу Django</title>
</head>
<body>
    <form method="POST">
        {% csrf_token %}
    <table>
        {{ form.as_table }}
    </table>
    <input type="submit" value="Send" >
</form>
</body>
</html>


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

 

Длина полей

Для полей, которые требуют ввода текста, - например, CharField и подобных, иногда требуется ограничивать количество вводимых символов.

Это можно сделать с помощью параметров: max_length - максимальное количество символов и min_length - минимальное количество символов.

Например, в поле, созданном с помощью следующего кода:

from django import forms


class UserForm(forms.Form):
    name = forms.CharField(label='Имя', help_text='Введите свое имя', min_length=2, max_length=10)
    age = forms.IntegerField(label='Ваш возраст?', help_text='Введите свой возраст')
    reklama = forms.BooleanField(label='Coглacны получать рекламу?', required=False)

Теперь у нас не получится ввести в поле имени более 10 символов.

 

Минимальное и максимальное число

По аналогии для числовых полей IntegerField, DecimalField и FloatField можно устанавливать параметры: max_value и min_value, которые задают соответственно максимально допустимое и минимально допустимое значения.

Для поля DecimalField дополнительно можно задать еще один параметр - decimal_places, который определяет максимальное количество знаков после запятой.

Например, в поле, созданного с помощью следующего кода:

age = forms.IntegerField(min_value=1, max_value=100)
weight = forms.DecimalField(min_value=3, max_value=200, decimal_places=2)

 

is_valid()

Рассмотренные выше атрибуты позволяют валидировать значения при вводе на стороне клиента.

Однако на практике, пользователи, имея определенные навыки, могут все равно отправить форму с заведомо некорректными данными.

Сейчас если мы попробуем отправить форму, не заполнив одно из обязательных полей, то увидим следующее:

Например, через инструменты для разработчиков в веб-браузере можно подправить исходный код формы, добавив ей атрибут novalidate, который отключает клиентскую валидацию.

Поэтому проверку данных на валидность надо выполнять и на стороне сервера. Для этого у формы вызывается метод is_valid(), который возвращает True, если данные корректны, и False - если данные некорректны.

Чтобы использовать этот метод, надо создать объект формы и передать ей пришедшие из запроса данные.

Итак, определим следующее представление в файле views.py:

from django.shortcuts import render
from django.http import HttpResponse
from .forms import UserForm


def index(request):
    if request.method == 'POST':
        userform = UserForm(request.POST)
        if userform.is_valid():
            name = userform.cleaned_data['name']
            return HttpResponse(f'<h2>Hello, {name}</h2>')
        else:
            return HttpResponse('Invalid data')
    else:
        userform = UserForm()
        return render(request, 'index.html', {'form': userform})


Если был получен POST-запрос, то в сначала заполняем форму пришедшими данными:

userform = UserForm(request.POST)


Потом проверяем их корректность:

if userform.is_valid():


После проверки на валидность, мы можем получить очищенные данные, через объект cleaned_data, если данные корректны:

name = userform.cleaned_data['name']

cleaned_data это словарь, который заполняется очищенными параметрами запроса, при вызове метода валидации формы is_valid(). Параметры запроса будут доступны в виде ключей этого словаря, в данном случае это 'name', 'age' и 'reklama'.

Если данные некорректны, можно предусмотреть альтернативный вывод:

return HttpResponse('Invalid data')


Для тестирования формы можно установить в ней атрибут novalidate:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Учу Django</title>
</head>
<body>
    <form method="POST" novalidate>
        {% csrf_token %}
    <table>
        {{ form.as_table }}
    </table>
    <input type="submit" value="Send" >
</form>
</body>
</html>


Теперь если мы попробуем отправить форму, не заполнив один из полей, то уже метод вернет нам ошибку.


  • Комментария
Будьте вежливы и соблюдайте наши принципы сообщества. Пожалуйста, не оставляйте решения и подсказки в комментариях, для этого есть отдельный форум.
Оставить комментарий

Я так понимаю в первый раз required не должно быть. 

Например, в поле, созданном с помощью следующего кода:

 Для тестирования формы можно установить в ней атрибут novalidate:

 И тут:
Однако практически пользователи, имея определенные навыки, могут все равно отправить форму с заведомо некорректными данными.
Лучше:
Однако на практике пользователи, имея определенные навыки, могут все равно отправить форму с заведомо некорректными данными.

@Георгий_Тимофеев, исправил, спасибо за помощь в улучшении курса.

почему-то слова кучкуются

@Дмитрий_Чекмасов, А какой код у вас в шаблоне?

@Илья_Перминов, все по уроку, обычно вручную всё ввожу, но тут даже полное копирование не помогает. Хотя пример с тремя вариантами работал как надо