Работа с формами
О документе
Этот документ предоставляет введение в основы веб-форм и их обработку в Django. Для более подробного ознакомления со специфическими областями API форм см. API форм, Поля форм и Валидация форм и полей.
Если вы не планируете создавать веб-сайты и приложения, которые только публикуют контент и не принимают входные данные от посетителей, вам необходимо понимать и использовать формы.
Django предоставляет набор инструментов и библиотек, которые помогут вам создавать формы для приема входных данных от посетителей сайта, а затем обрабатывать и отвечать на эти данные.
HTML-формы
В HTML форма представляет собой набор элементов внутри <form>...</form>, которые позволяют посетителю выполнять такие действия, как ввод текста, выбор вариантов, манипулирование объектами или элементами управления и т. д., а затем отправлять эту информацию на сервер.
Некоторые из этих элементов интерфейса формы — текстовые поля или флажки — довольно простые и встроены в сам HTML. Другие гораздо сложнее; интерфейс, который отображает календарь выбора даты, позволяет перемещать ползунок или манипулировать элементами управления, как правило, использует JavaScript и CSS, а также HTML-элементы форм <input> для достижения этих эффектов.
Помимо своих <input> элементов, форма должна указывать две вещи:
- куда: URL, на который должны быть возвращены данные, соответствующие вводу пользователя
- как: 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 в Django, обеспечивает больший контроль доступа.
С другой стороны, GET подходит для таких вещей, как форма поиска по веб-сайту, потому что URL, представляющие запрос GET легко закрепить закладкой, поделиться или повторно отправить.
Роль Django в формах
Обработка форм — это сложное дело. Рассмотрим административную панель Django, где множество данных разных типов могут потребоваться для отображения в форме, рендеринга в HTML, редактирования с помощью удобного интерфейса, возвращения на сервер, проверки и очистки, а затем сохранения или передачи для дальнейшей обработки.
Функциональность форм Django может упростить и автоматизировать огромные части этой работы, а также сделать это более безопасно, чем большинство программистов могли бы сделать в коде, написанном самостоятельно.
Django обрабатывает три distinct части работы, связанной с формами:
- подготовка и перестройка данных для их подготовки к рендерингу
- создание 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 «виджетом» — частью механизма пользовательского интерфейса. Для каждого типа поля есть соответствующий виджет по умолчанию класс виджета, но эти виджеты можно переопределять по мере необходимости.
Создание, обработка и рендеринг форм
При рендеринге объекта в 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. Он отобразит текстовое поле с подписью «Ваше имя:» и кнопку «ОК». Если в контексте шаблона содержится переменная 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, мы возвращаемся в шаблон с формой. На этот раз форма больше не пустая (несвязанная), поэтому 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-разметку Django's языка шаблонов из этого {{ form }}.
Формы и защита от межсайтовых поддельных запросов
Django поставляется с удобной в использовании защитой от межсайтовых поддельных запросов. При отправке формы через POST с включённой защитой CSRF вы должны использовать тег шаблона csrf_token, как в предыдущем примере. Однако, поскольку защита CSRF напрямую не связана с формами в шаблонах, этот тег опущен из последующих примеров в этом документе.
HTML5 типы ввода и проверка браузера
Если ваша форма содержит URLField, EmailField или любой тип целого числа, Django будет использовать url, email и number HTML5 типы ввода. По умолчанию браузеры могут применять собственную проверку на этих полях, которая может быть строже, чем проверка Django. Если вы хотите отключить это поведение, установите атрибут novalidate на теге form, или укажите другой виджет на поле, например TextInput.
Теперь у нас есть работающая веб-форма, описанная Django Form, обработанная представлением и отображаемая как HTML <form>.
Этого достаточно для начала, но фреймворк форм предоставляет гораздо больше возможностей. После понимания основ описанного выше процесса вы должны быть готовы понять другие особенности системы форм и готовы узнать больше о базовых механизмах.
Подробнее о классах форм Django
Все классы форм создаются как подклассы либо 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, CharField. В этом случае наша форма имеет четыре поля: subject, message, sender и cc_myself. CharField, EmailField и BooleanField — всего лишь три доступных типа полей; полный список можно найти в Поля форм.
Виджеты
У каждого поля формы есть соответствующий Класс виджета, который, в свою очередь, соответствует HTML-виджету формы, например, <input
type="text">.
В большинстве случаев у поля будет разумный виджет по умолчанию. Например, по умолчанию у CharField будет виджет TextInput, который создаёт <input type="text"> в HTML. Если вам нужен <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>, который используется тегом соответствующей метки. Это важно для обеспечения доступности форм для вспомогательных технологий, таких как программы чтения с экрана. Также можно настроить способ генерации меток и идентификаторов.
См. Вывод форм как 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_emailв приведенном выше примере). Если вы создаёте метку вручную, вы можете использовать его вместоlabel_tag. Он также полезен, например, если у вас есть некоторый встроенный JavaScript и вы хотите избежать жёсткого кодирования идентификатора поля. -
{{ field.value }} - Значение поля. Например,
someone@example.com. -
{{ field.html_name }} - Имя поля, которое будет использоваться в атрибуте name элемента input. Принимает во внимание префикс формы, если он был задан.
-
{{ 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.
Проход по скрытым и видимым полям
Django предоставляет два метода для формы, которые позволяют проходить по скрытым и видимым полям независимо: hidden_fields() и visible_fields(). Вот модификация предыдущего примера, использующего эти два метода:
{# Include the hidden fields #}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{# Include the visible fields #}
{% for field in form.visible_fields %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
</div>
{% endfor %}
В этом примере ошибки скрытых полей не обрабатываются. Обычно ошибка в скрытом поле указывает на вмешательство в форму, так как обычное взаимодействие с формой не изменяет их. Однако вы можете легко вставить отображение ошибок для таких ошибок формы.
Многократно используемые шаблоны форм
Если ваш сайт использует одинаковую логику рендеринга форм в нескольких местах, вы можете уменьшить дублирование, сохранив цикл формы в отдельном шаблоне и используя тег 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 %}
Если вы часто делаете это, вы можете рассмотреть создание настраиваемого тега включения.
Дополнительные темы
Это основы, но формы могут делать гораздо больше:
-
Наборы форм
- Использование начальных данных с набором форм
- Ограничение максимального количества форм
- Валидация набора форм
- Валидация количества форм в наборе форм
- Обработка порядка и удаления форм
- Добавление дополнительных полей в набор форм
- Передача пользовательских параметров формам набора форм
- Настройка префикса набора форм
- Использование набора форм в представлениях и шаблонах
- Создание форм из моделей
-
Активности формы (класс
Media)
См. также
- Справочник по формам
- Покрывает полную справочную информацию по API, включая поля форм, виджеты форм и валидацию форм и полей.
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/2.1/topics/forms/index/