Проверка (валидация) данных
Теоретически пользователь может ввести в форму и отправить какие угодно данные. Однако не все данные бывают уместными или корректными. Например, в поле для возраста пользователь может ввести отрицательное или четырехзначное число, что вряд ли может считаться корректным возрастом. В 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>
Теперь если мы попробуем отправить форму, не заполнив один из полей, то уже метод вернет нам ошибку.