Работа с формами¶
Об этом документе
Этот документ содержит введение в основы веб-форм и то, как они обрабатываются в Django. Для более детального рассмотрения конкретных областей API форм смотрите API форм, Поля формы и Валидация форм и полей.
Если вы не планируете создавать веб-сайты и приложения, которые будут только публиковать содержимое и не будут принимать данные от посетителей, вам необходимо понимать и использовать формы.
Django предоставляет ряд инструментов и библиотек, которые помогут вам создать формы, принимающие ввод от посетителей сайта, а затем обрабатывающие и отвечающие на него.
HTML-формы¶
В HTML форма - это набор элементов внутри <form>...</form>
, которые позволяют посетителю выполнять такие действия, как ввод текста, выбор опций, манипулирование объектами или элементами управления и так далее, а затем отправлять эту информацию обратно на сервер.
Некоторые из этих элементов интерфейса формы - ввод текста или флажки - встроены в сам HTML. Другие гораздо сложнее; интерфейс, который открывает окно выбора даты или позволяет перемещать ползунок или манипулировать элементами управления, обычно использует JavaScript и CSS, а также элементы HTML формы <input>
для достижения этих эффектов.
Помимо элементов <input>
, форма должна содержать два элемента:
- where: URL, по которому должны быть возвращены данные, соответствующие введенным пользователем
- how: метод HTTP, с помощью которого должны быть возвращены данные
В качестве примера, форма входа для администратора Django содержит несколько элементов <input>
: один из type="text"
для имени пользователя, один из type="password"
для пароля и один из type="submit"
для кнопки «Войти». Он также содержит некоторые скрытые текстовые поля, которые пользователь не видит, и которые Django использует для определения того, что делать дальше.
Он также сообщает браузеру, что данные формы должны быть отправлены на URL, указанный в атрибуте <form>
“action
- /admin/
- и что они должны быть отправлены с использованием механизма HTTP, указанного в атрибуте method
- post
.
Когда срабатывает элемент <input type="submit" value="Log in">
, данные возвращаются в /admin/
.
GET
и POST
.¶
GET
и POST
- единственные методы HTTP, которые следует использовать при работе с формами.
Форма входа в Django возвращается с помощью метода POST
, в котором браузер упаковывает данные формы, кодирует их для передачи, отправляет на сервер, а затем получает ответ.
GET
, напротив, объединяет предоставленные данные в строку и использует ее для составления URL. URL содержит адрес, по которому должны быть отправлены данные, а также ключи и значения данных. Вы можете увидеть это в действии, если выполните поиск в документации Django, который выдаст URL вида https://docs.djangoproject.com/search/?q=forms&release=1
.
GET
и POST
обычно используются для разных целей.
Любой запрос, который может быть использован для изменения состояния системы - например, запрос, который вносит изменения в базу данных - должен использовать POST
. GET
следует использовать только для запросов, которые не влияют на состояние системы.
GET
также не подходит для формы пароля, поскольку пароль будет отображаться в URL, а значит, и в истории браузера и журналах сервера, причем открытым текстом. Он также не подходит для больших объемов данных или для двоичных данных, таких как изображение. Веб-приложение, использующее запросы GET
для административных форм, представляет собой угрозу безопасности: злоумышленнику может быть легко сымитировать запрос формы, чтобы получить доступ к чувствительным частям системы. POST
в сочетании с другими средствами защиты, такими как CSRF protection в Django, обеспечивает больший контроль над доступом.
С другой стороны, GET
подходит для таких вещей, как форма веб-поиска, потому что URL-адреса, которые представляют запрос GET
, можно легко добавить в закладки, поделиться ими или отправить повторно.
Роль Django в формах¶
Работа с формами - сложное дело. Рассмотрим админку Django, где множество элементов данных нескольких различных типов могут быть подготовлены для отображения в форме, отображены в виде HTML, отредактированы с помощью удобного интерфейса, возвращены на сервер, проверены и очищены, а затем сохранены или переданы для дальнейшей обработки.
Функциональность форм Django может упростить и автоматизировать огромную часть этой работы, а также сделать это более безопасно, чем большинство программистов могли бы сделать в коде, который они написали сами.
Django обрабатывает три различные части работы, связанной с формами:
- подготовка и реструктуризация данных, чтобы сделать их готовыми к визуализации
- создание HTML-форм для данных
- получение и обработка представленных форм и данных от клиента
Можно написать код, который будет делать все это вручную, но Django может позаботиться обо всем этом за вас.
Формы в Django¶
Мы кратко описали HTML-формы, но HTML <form>
- это только одна часть необходимого механизма.
В контексте веб-приложения «форма» может относиться к HTML <form>
, или к Django Form
, который ее создает, или к структурированным данным, возвращаемым при отправке, или к сквозной рабочей коллекции этих частей.
Класс Django Form
¶
В основе этой системы компонентов лежит класс Django Form
. Точно так же, как модель Django описывает логическую структуру объекта, его поведение и то, как его части представлены нам, класс Form
описывает форму и определяет, как она работает и отображается.
Подобно тому, как поля класса модели отображаются на поля базы данных, поля класса формы отображаются на элементы HTML-формы <input>
. (Поле ModelForm
отображает поля класса модели на элементы HTML-формы <input>
через Form
; на этом основана админка Django).
Поля формы сами по себе являются классами; они управляют данными формы и выполняют проверку при отправке формы. DateField
и FileField
обрабатывают совершенно разные типы данных и должны делать с ними разные вещи.
Поле формы представляется пользователю в браузере как HTML «виджет» - часть пользовательского интерфейса. Каждый тип поля имеет соответствующее значение по умолчанию Widget class, но оно может быть переопределено по мере необходимости.
Создание, обработка и визуализация форм¶
При визуализации объекта в Django мы обычно:
- получить его в представлении (например, получить его из базы данных)
- передать его в контекст шаблона
- развернуть его в HTML-разметку с помощью переменных шаблона
Рендеринг формы в шаблоне включает в себя практически ту же работу, что и рендеринг любого другого типа объекта, но есть несколько ключевых различий.
В случае экземпляра модели, не содержащего данных, редко, если вообще когда-либо, будет полезно что-то делать с ним в шаблоне. С другой стороны, имеет смысл отобразить незаполненную форму - именно это мы делаем, когда хотим, чтобы пользователь заполнил ее.
Поэтому, когда мы работаем с экземпляром модели в представлении, мы обычно получаем его из базы данных. Когда мы работаем с формой, мы обычно создаем ее в представлении.
Когда мы создаем форму, мы можем оставить ее пустой или предварительно заполнить, например, с помощью:
- данные из сохраненного экземпляра модели (как в случае с админскими формами для редактирования)
- данные, которые мы собрали из других источников
- данные, полученные от предыдущей отправки HTML-формы
Последний из этих случаев наиболее интересен, поскольку именно он позволяет пользователям не только читать сайт, но и отправлять на него информацию.
Построение формы¶
Работа, которую необходимо выполнить¶
Предположим, вы хотите создать простую форму на своем сайте, чтобы получить имя пользователя. Вам понадобится что-то подобное в вашем шаблоне:
<form action="/your-name/" method="post">
<label for="your_name">Your name: </label>
<input id="your_name" type="text" name="your_name" value="{{ current_name }}">
<input type="submit" value="OK">
</form>
Это указывает браузеру вернуть данные формы в URL /your-name/
, используя метод POST
. Он отобразит текстовое поле с надписью «Ваше имя:» и кнопку с надписью «OK». Если контекст шаблона содержит переменную current_name
, она будет использована для предварительного заполнения поля your_name
.
Вам понадобится представление, которое отображает шаблон, содержащий HTML-форму, и которое может предоставлять поле current_name
по мере необходимости.
Когда форма отправлена, запрос POST
, который отправляется на сервер, будет содержать данные формы.
Теперь вам также понадобится представление, соответствующее этому URL /your-name/
, которое будет находить соответствующие пары ключ/значение в запросе, а затем обрабатывать их.
Это очень простая форма. На практике форма может содержать десятки или сотни полей, многие из которых должны быть предварительно заполнены, и мы можем ожидать, что пользователь пройдет цикл редактирования-отправки несколько раз, прежде чем завершит операцию.
Мы можем потребовать некоторой проверки в браузере, даже до отправки формы; мы можем захотеть использовать гораздо более сложные поля, которые позволят пользователю делать такие вещи, как выбор даты из календаря и так далее.
На данном этапе гораздо проще заставить Django сделать большую часть этой работы за нас.
Создание формы в Django¶
Класс Form
¶
Мы уже знаем, как должна выглядеть наша HTML-форма. Наша отправная точка для нее в Django такова:
from django import forms
class NameForm(forms.Form):
your_name = forms.CharField(label='Your name', max_length=100)
Это определяет класс Form
с одним полем (your_name
). Мы применили к полю удобную для человека метку, которая появится в <label>
при его отображении (хотя в данном случае указанная нами метка label
фактически является той же самой, которая была бы сгенерирована автоматически, если бы мы ее опустили).
Максимально допустимая длина поля определяется max_length
. Это делает две вещи. Она накладывает maxlength="100"
на HTML <input>
(таким образом, браузер должен предотвратить ввод пользователем более чем этого количества символов). Это также означает, что когда Django получит форму обратно от браузера, он проверит длину данных.
Экземпляр Form
имеет метод is_valid()
, который запускает процедуры валидации для всех его полей. При вызове этого метода, если все поля содержат достоверные данные, он будет:
- возврат
True
- поместить данные формы в ее атрибут
cleaned_data
.
Вся форма при первом отображении будет выглядеть следующим образом:
<label for="your_name">Your name: </label>
<input id="your_name" type="text" name="your_name" maxlength="100" required>
Обратите внимание, что он **не включает в себя теги <form>
или кнопку отправки. Мы должны сами предусмотреть их в шаблоне.
Взгляд¶
Данные формы, отправленные обратно на сайт Django, обрабатываются представлением, обычно тем же представлением, которое опубликовало форму. Это позволяет нам повторно использовать часть той же логики.
Для работы с формой нам нужно инстанцировать ее в представлении для URL, где мы хотим ее опубликовать:
from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import NameForm
def get_name(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = NameForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
# ...
# redirect to a new URL:
return HttpResponseRedirect('/thanks/')
# if a GET (or any other method) we'll create a blank form
else:
form = NameForm()
return render(request, 'name.html', {'form': form})
Если мы придем к этому представлению с запросом GET
, оно создаст пустой экземпляр формы и поместит его в контекст шаблона для отображения. Это то, что мы можем ожидать, что произойдет при первом посещении URL.
Если форма отправлена с помощью запроса POST
, представление снова создаст экземпляр формы и заполнит его данными из запроса: form = NameForm(request.POST)
Это называется «привязка данных к форме» (теперь это связанная форма).
Мы вызываем метод формы is_valid()
; если он не True
, мы возвращаемся к шаблону с формой. На этот раз форма уже не пустая (unbound), поэтому HTML-форма будет заполнена ранее представленными данными, где их можно будет отредактировать и исправить при необходимости.
Если is_valid()
равно True
, то теперь мы сможем найти все проверенные данные формы в ее атрибуте cleaned_data
. Мы можем использовать эти данные для обновления базы данных или другой обработки перед отправкой HTTP-переадресации браузеру, указывающей ему, куда идти дальше.
Шаблон¶
Нам не нужно многого делать в нашем шаблоне name.html
:
<form action="/your-name/" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit">
</form>
Все поля формы и их атрибуты будут распакованы в HTML-разметку из этого {{ form }}
языком шаблонов Django.
Формы и защита от подделки межсайтовых запросов
Django поставляется с простым в использовании protection against Cross Site Request Forgeries. При отправке формы через POST
с включенной защитой CSRF вы должны использовать тег шаблона csrf_token
, как в предыдущем примере. Однако, поскольку защита от CSRF не связана напрямую с формами в шаблонах, этот тег опущен в следующих примерах в этом документе.
Типы ввода HTML5 и проверка браузера
Если ваша форма включает URLField
, EmailField
или любой целочисленный тип поля, Django будет использовать типы ввода url
, email
и number
HTML5. По умолчанию браузеры могут применять свою собственную проверку для этих полей, которая может быть более строгой, чем проверка Django. Если вы хотите отключить это поведение, установите атрибут novalidate
в теге form
или укажите другой виджет для поля, например TextInput
.
Теперь у нас есть рабочая веб-форма, описанная Django Form
, обработанная представлением и отображенная в виде HTML <form>
.
Это все, что вам нужно для начала работы, но система форм предоставляет вам гораздо больше возможностей. Как только вы поймете основы процесса, описанного выше, вы должны быть готовы к пониманию других возможностей системы форм и готовы узнать немного больше о механизме, лежащем в ее основе.
Подробнее о классах Django Form
¶
Все классы форм создаются как подклассы либо django.forms.Form
, либо django.forms.ModelForm
. Вы можете считать ModelForm
подклассом Form
. Form
и ModelForm
фактически наследуют общую функциональность от (частного) класса BaseForm
, но эта деталь реализации редко бывает важной.
Модели и формы
На самом деле, если ваша форма будет использоваться для прямого добавления или редактирования модели Django, ModelForm может сэкономить вам много времени, усилий и кода, потому что она создаст форму, вместе с соответствующими полями и их атрибутами, из класса Model
.
Связанные и несвязанные экземпляры форм¶
Различие между Связанные и несвязанные формы является важным:
- Несвязанная форма не имеет данных, связанных с ней. При отображении пользователю она будет пустой или будет содержать значения по умолчанию.
- Связанная форма содержит отправленные данные и, следовательно, может быть использована для определения того, являются ли эти данные действительными. Если отображается недействительная связанная форма, она может содержать встроенные сообщения об ошибках, сообщающие пользователю, какие данные необходимо исправить.
Атрибут формы is_bound
подскажет вам, есть ли у формы данные, привязанные к ней, или нет.
Подробнее о полях¶
Рассмотрим более полезную форму, чем наш минимальный пример выше, которую мы могли бы использовать для реализации функции «свяжитесь со мной» на персональном сайте:
from django import forms
class ContactForm(forms.Form):
subject = forms.CharField(max_length=100)
message = forms.CharField(widget=forms.Textarea)
sender = forms.EmailField()
cc_myself = forms.BooleanField(required=False)
В нашей предыдущей форме использовалось одно поле, your_name
, a CharField
. В данном случае наша форма имеет четыре поля: subject
, message
, sender
и cc_myself
. CharField
, EmailField
и BooleanField
- это только три из доступных типов полей; полный список можно найти в Поля формы.
Виджеты¶
Каждое поле формы имеет соответствующий Widget class, который в свою очередь соответствует виджету HTML-формы, например <input type="text">
.
В большинстве случаев поле будет иметь разумный виджет по умолчанию. Например, по умолчанию поле CharField
будет иметь виджет TextInput
, который в HTML выдает <input type="text">
. Если вам нужно <textarea>
вместо этого, вы укажете соответствующий виджет при определении поля формы, как мы это сделали для поля message
.
Полевые данные¶
Какими бы ни были данные, представленные в форме, как только они будут успешно проверены вызовом is_valid()
(и is_valid()
вернет True
), проверенные данные формы окажутся в словаре form.cleaned_data
. Эти данные будут красиво преобразованы в типы Python для вас.
Примечание
На данный момент вы все еще можете получить доступ к непроверенным данным непосредственно из request.POST
, но проверенные данные лучше.
В приведенном выше примере контактной формы cc_myself
будет булевым значением. Аналогично, такие поля, как IntegerField
и FloatField
преобразуют значения в Python int
и float
соответственно.
Вот как данные формы могут быть обработаны в представлении, которое обрабатывает эту форму:
from django.core.mail import send_mail
if form.is_valid():
subject = form.cleaned_data['subject']
message = form.cleaned_data['message']
sender = form.cleaned_data['sender']
cc_myself = form.cleaned_data['cc_myself']
recipients = ['info@example.com']
if cc_myself:
recipients.append(sender)
send_mail(subject, message, sender, recipients)
return HttpResponseRedirect('/thanks/')
Совет
Подробнее об отправке электронной почты из Django смотрите Отправка электронной почты.
Некоторые типы полей требуют дополнительной обработки. Например, файлы, загружаемые с помощью формы, должны обрабатываться по-другому (они могут быть получены из request.FILES
, а не из request.POST
). Подробнее о том, как обрабатывать загрузку файлов с помощью формы, смотрите Привязка загруженных файлов к форме.
Работа с шаблонами форм¶
Все, что вам нужно сделать, чтобы поместить вашу форму в шаблон, это поместить экземпляр формы в контекст шаблона. Таким образом, если ваша форма называется form
в контексте, {{ form }}
отобразит ее элементы <label>
и <input>
соответствующим образом.
Параметры рендеринга формы¶
Дополнительная мебель для шаблонов форм
Не забывайте, что вывод формы не включает окружающие теги <form>
или элемент управления формы submit
. Вы должны будете предоставить их сами.
Однако для пар <label>
/<input>
существуют и другие варианты вывода:
{{ form.as_table }}
будет отображать их как ячейки таблицы, обернутые в теги<tr>
{{ form.as_p }}
будет отображать их обернутыми в теги<p>
{{ form.as_ul }}
будет отображать их обернутыми в теги<li>
Обратите внимание, что вам придется самостоятельно предоставить окружающие элементы <table>
или <ul>
.
Вот вывод {{ form.as_p }}
для нашего экземпляра ContactForm
:
<p><label for="id_subject">Subject:</label>
<input id="id_subject" type="text" name="subject" maxlength="100" required></p>
<p><label for="id_message">Message:</label>
<textarea name="message" id="id_message" required></textarea></p>
<p><label for="id_sender">Sender:</label>
<input type="email" name="sender" id="id_sender" required></p>
<p><label for="id_cc_myself">Cc myself:</label>
<input type="checkbox" name="cc_myself" id="id_cc_myself"></p>
Обратите внимание, что каждое поле формы имеет атрибут ID, установленный в id_<field-name>
, на который ссылается сопровождающий тег label. Это важно для обеспечения доступности форм для вспомогательных технологий, таких как программы для чтения с экрана. Вы также можете customize the way in which labels and ids are generated.
Подробнее об этом см. в разделе Вывод форм в формате HTML.
Рендеринг полей вручную¶
Нам не обязательно позволять Django распаковывать поля формы; при желании мы можем сделать это вручную (что позволит нам, например, изменить порядок полей). Каждое поле доступно как атрибут формы с помощью {{ form.name_of_field }}
, и в шаблоне Django будет отображаться соответствующим образом. Например:
{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ form.subject.errors }}
<label for="{{ form.subject.id_for_label }}">Email subject:</label>
{{ form.subject }}
</div>
<div class="fieldWrapper">
{{ form.message.errors }}
<label for="{{ form.message.id_for_label }}">Your message:</label>
{{ form.message }}
</div>
<div class="fieldWrapper">
{{ form.sender.errors }}
<label for="{{ form.sender.id_for_label }}">Your email address:</label>
{{ form.sender }}
</div>
<div class="fieldWrapper">
{{ form.cc_myself.errors }}
<label for="{{ form.cc_myself.id_for_label }}">CC yourself?</label>
{{ form.cc_myself }}
</div>
Полные элементы <label>
также могут быть сгенерированы с помощью label_tag()
. Например:
<div class="fieldWrapper">
{{ form.subject.errors }}
{{ form.subject.label_tag }}
{{ form.subject }}
</div>
Рендеринг сообщений об ошибках формы¶
Цена этой гибкости - немного больше работы. До сих пор нам не приходилось беспокоиться о том, как отображать ошибки формы, поскольку об этом уже позаботились. В этом примере нам пришлось позаботиться об ошибках для каждого поля и об ошибках для формы в целом. Обратите внимание на {{ form.non_field_errors }}
в верхней части формы и поиск ошибок в шаблоне для каждого поля.
Использование {{ form.name_of_field.errors }}
выводит список ошибок формы, отображаемый в виде неупорядоченного списка. Это может выглядеть следующим образом:
<ul class="errorlist">
<li>Sender is required.</li>
</ul>
Список имеет CSS-класс errorlist
, чтобы вы могли стилизовать его внешний вид. Если вы хотите дополнительно настроить отображение ошибок, вы можете сделать это, перебирая их в цикле:
{% if form.subject.errors %}
<ol>
{% for error in form.subject.errors %}
<li><strong>{{ error|escape }}</strong></li>
{% endfor %}
</ol>
{% endif %}
Ошибки, не относящиеся к полю (и/или ошибки скрытого поля, которые отображаются в верхней части формы при использовании таких помощников, как form.as_p()
), будут отображаться с дополнительным классом nonfield
, чтобы помочь отличить их от ошибок, относящихся к полю. Например, {{ form.non_field_errors }}
будет выглядеть следующим образом:
<ul class="errorlist nonfield">
<li>Generic validation error</li>
</ul>
Подробнее об ошибках, стилизации и работе с атрибутами формы в шаблонах смотрите в API форм.
Перебор полей формы¶
Если вы используете один и тот же HTML для каждого из полей формы, вы можете уменьшить количество дублирующегося кода, перебирая каждое поле по очереди с помощью цикла {% for %}
:
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
{% if field.help_text %}
<p class="help">{{ field.help_text|safe }}</p>
{% endif %}
</div>
{% endfor %}
Полезные атрибуты на {{ field }}
включают:
{{ field.label }}
- Метка поля, например,
Email address
. {{ field.label_tag }}
Метка поля, обернутая в соответствующий тег HTML
<label>
. Это включает в себяlabel_suffix
формы. Например, по умолчаниюlabel_suffix
- это двоеточие:<label for="id_email">Email address:</label>
{{ field.id_for_label }}
- ID, который будет использоваться для этого поля (
id_email
в примере выше). Если вы создаете метку вручную, вы можете использовать этот параметр вместоlabel_tag
. Это также полезно, например, если у вас есть встроенный JavaScript и вы хотите избежать жесткого кодирования ID поля. {{ field.value }}
- Значение поля. например,
someone@example.com
. {{ field.html_name }}
- Имя поля, которое будет использоваться в поле имени элемента ввода. При этом учитывается префикс формы, если он был задан.
{{ field.help_text }}
- Любой текст справки, связанный с полем.
{{ field.errors }}
- Выводит
<ul class="errorlist">
, содержащий все ошибки валидации, соответствующие данному полю. Вы можете настроить представление ошибок с помощью цикла{% for error in field.errors %}
. В этом случае каждый объект в цикле представляет собой строку, содержащую сообщение об ошибке. {{ field.is_hidden }}
- Этот атрибут имеет значение
True
, если поле формы является скрытым полем, иFalse
в противном случае. Он не особенно полезен в качестве переменной шаблона, но может быть полезен в условных тестах, таких как:
{% if field.is_hidden %}
{# Do something special #}
{% endif %}
{{ field.field }}
- Экземпляр
Field
из класса формы, который обернут этимBoundField
. Вы можете использовать его для доступа к атрибутамField
, например,{{ char_field.field.max_length }}
.
См.также
Полный список атрибутов и методов приведен в разделе BoundField
.
Многоразовые шаблоны форм¶
Если ваш сайт использует одну и ту же логику рендеринга форм в нескольких местах, вы можете сократить дублирование, сохранив цикл формы в отдельном шаблоне и используя тег include
для повторного использования в других шаблонах:
# In your form template:
{% include "form_snippet.html" %}
# In form_snippet.html:
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
</div>
{% endfor %}
Если объект формы, передаваемый в шаблон, имеет другое имя в контексте, его можно псевдоименовать с помощью аргумента with
тега include
:
{% include "form_snippet.html" with form=comment_form %}
Если вы часто делаете это, вы можете подумать о создании пользовательского inclusion tag.
Дополнительные темы¶
Здесь описаны основы, но формы могут делать гораздо больше:
- Формсеты
- Использование исходных данных с помощью набора форм
- Ограничение максимального количества форм
- Ограничение максимального количества инстанцированных форм
- Валидация форм
- Проверка количества форм в наборе форм
- Работа с заказами и удалением форм
- Добавление дополнительных полей в набор форм
- Передача пользовательских параметров формам набора форм
- Настройка префикса набора форм
- Использование набора форм в представлениях и шаблонах
- Создание форм из моделей
- Активы формы (класс
Media
)
См.также
- The Forms Reference
- Охватывает полный справочник API, включая поля форм, виджеты форм, а также валидацию форм и полей.