Работа с формами ¶
Об этом документе
Этот документ представляет собой введение в основы веб-форм и то, как они обрабатываются в Django. Для более подробного рассмотрения конкретных областей форм API см Формы API , поля форм , а также формы и проверки на местах .
Если вы не планируете создавать веб-сайты и приложения, которые ничего не делают, кроме публикации контента и не принимают ввод от ваших посетителей, вам нужно будет понимать и использовать формы.
Django предоставляет ряд инструментов и библиотек, которые помогут вам создавать формы, принимающие ввод от посетителей сайта, а затем обрабатывающие вводимые данные и отвечающие на них.
HTML-формы ¶
В HTML форма - это набор элементов внутри, <form>...</form>
которые позволяют посетителю делать такие вещи, как ввод текста, выбирать параметры, манипулировать объектами или элементами управления и т. Д., А затем отправлять эту информацию обратно на сервер.
Некоторые из этих элементов интерфейса формы - ввод текста или флажки - встроены в сам HTML. Другие намного сложнее; интерфейс, который открывает окно выбора даты или позволяет перемещать ползунок или управлять элементами управления, обычно использует JavaScript и CSS, а также <input>
элементы формы HTML для достижения этих эффектов.
Помимо своих <input>
элементов, форма должна определять две вещи:
- где : URL-адрес, по которому должны быть возвращены данные, соответствующие вводу пользователя
- как : HTTP-метод, который должен возвращать данные
Например, форма входа в систему для администратора Django содержит несколько
<input>
элементов: один type="text"
для имени пользователя, один
type="password"
для пароля и один type="submit"
для кнопки «Войти». Он также содержит некоторые скрытые текстовые поля, которые пользователь не видит, которые Django использует, чтобы определить, что делать дальше.
Он также сообщает браузеру , что данные формы должны быть отправлены на адрес , указанный в <form>
«s 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
, в сочетании с другими средствами защиты, такими как защита Django от CSRF, обеспечивает больший контроль над доступом.
С другой стороны, GET
он подходит для таких вещей, как форма веб-поиска, потому что URL-адреса, которые представляют GET
запрос, можно легко добавить в закладки, поделиться или повторно отправить.
Роль Django в формах ¶
Обработка форм - сложный бизнес. Рассмотрим админку Django, где может потребоваться подготовить множество элементов данных нескольких разных типов для отображения в форме, отрисовать как HTML, отредактировать с помощью удобного интерфейса, вернуть на сервер, проверить и очистить, а затем сохранить или передать. для дальнейшей обработки.
Функциональность форм Django может упростить и автоматизировать большую часть этой работы, а также сделать это более безопасно, чем большинство программистов смогли бы сделать в коде, который они написали сами.
Django выполняет три отдельные части работы, связанной с формами:
- подготовка и реструктуризация данных для подготовки к рендерингу
- создание HTML-форм для данных
- получение и обработка представленных форм и данных от клиента
Это возможно для написания кода , который делает все это вручную, но Django может взять на себя все это для вас.
Формы в Django ¶
Мы кратко описали формы HTML, но HTML <form>
- это лишь одна часть необходимого механизма.
В контексте веб-приложения «форма» может относиться к этому HTML
<form>
или к Django, Form
который его создает, или к структурированным данным, возвращаемым при отправке, или к непрерывной рабочей коллекции этих частей.
Джанго Form
класс ¶
В основе этой системы компонентов лежит Form
класс Django . Примерно так же, как модель Django описывает логическую структуру объекта, его поведение и способ представления нам его частей,
Form
класс описывает форму и определяет, как она работает и выглядит.
Подобно тому, как поля класса модели сопоставляются с полями базы данных, поля класса формы сопоставляются с <input>
элементами формы HTML . (A ModelForm
сопоставляет поля класса модели с <input>
элементами HTML-формы через a
Form
; это то, на чем основан администратор Django.)
Поля формы сами по себе являются классами; они управляют данными формы и выполняют проверку при отправке формы. A DateField
и a
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
запрос, который отправляется на сервер, будет содержать данные формы.
Теперь вам также понадобится представление, соответствующее этому /your-name/
URL-адресу, которое найдет соответствующие пары ключ / значение в запросе, а затем обработает их.
Это очень простая форма. На практике форма может содержать десятки или сотни полей, многие из которых могут нуждаться в предварительном заполнении, и мы можем ожидать, что пользователь проработает цикл редактирования-отправки несколько раз, прежде чем завершить операцию.
Нам может потребоваться некоторая проверка в браузере даже до отправки формы; мы могли бы захотеть использовать гораздо более сложные поля, которые позволяют пользователю делать такие вещи, как выбирать даты из календаря и так далее.
На этом этапе намного проще заставить 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.{{ form }}
Формы и защита от подделки межсайтовых запросов
Django поставляется с простой в использовании защитой от подделки межсайтовых запросов . При отправке формы через POST
с включенной защитой CSRF вы должны использовать csrf_token
тег шаблона, как в предыдущем примере. Однако, поскольку защита CSRF не связана напрямую с формами в шаблонах, этот тег опускается в следующих примерах в этом документе.
Типы ввода HTML5 и проверка браузера
Если ваша форма включает в URLField
себя
EmailField
целочисленный тип поля или любой другой, Django будет использовать типы ввода url
, email
и number
HTML5. По умолчанию браузеры могут применять к этим полям собственную проверку, которая может быть более строгой, чем проверка Django. Если вы хотите отключить это поведение, установите novalidate
атрибут в form
теге или укажите другой виджет в поле, например TextInput
.
Теперь у нас есть рабочая веб-форма, описываемая Django Form
, обрабатываемая представлением и отображаемая как HTML <form>
.
Это все, что вам нужно для начала, но фреймворк форм дает вам гораздо больше возможностей. Как только вы поймете основы описанного выше процесса, вы должны быть готовы понять другие особенности системы форм и узнать немного больше о базовом механизме.
Подробнее о 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
, a CharField
. В этом случае, наша форма имеет четыре поля: subject
, message
, sender
и
cc_myself
. CharField
, EmailField
и
BooleanField
это всего лишь три из доступных типов полей; полный список можно найти в полях формы .
Виджеты ¶
Каждое поле формы имеет соответствующий класс Widget , который, в свою очередь, соответствует виджету HTML-формы, например .<input
type="text">
В большинстве случаев в поле будет разумный виджет по умолчанию. Например, по умолчанию у a 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 = ['[email protected]']
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. Это важно для обеспечения доступности форм для вспомогательных технологий, таких как программы чтения с экрана. Вы также можете настроить способ создания ярлыков и идентификаторов .
Дополнительные сведения см. В разделе « Вывод форм в формате HTML» .
Отрисовка полей вручную ¶
Нам не нужно позволять Django распаковывать поля формы; мы можем сделать это вручную, если захотим (например, позволив нам изменить порядок полей). Каждое поле доступно как атрибут используемой формы , а в шаблоне Django будет отображаться соответствующим образом. Например:{{ form.name_of_field }}
{{ 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 }}
Ярлык поля заключен в соответствующий
<label>
тег HTML . Это включает формуlabel_suffix
. Например, по умолчаниюlabel_suffix
используется двоеточие:<label for="id_email">Email address:</label>
{{ field.id_for_label }}
- Идентификатор, который будет использоваться для этого поля (
id_email
в примере выше). Если вы создаете этикетку вручную, вы можете использовать это вместоlabel_tag
. Это также полезно, например, если у вас есть встроенный JavaScript и вы хотите избежать жесткого кодирования идентификатора поля. {{ field.value }}
- Значение поля. напр
[email protected]
. {{ 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 %}
Если вы обнаружите, что делаете это часто, вы можете подумать о создании настраиваемого тега включения .
Дальнейшие темы ¶
Это охватывает основы, но формы могут делать гораздо больше:
- Наборы форм
- Использование исходных данных с набором форм
- Ограничение максимального количества форм
- Ограничение максимального количества экземпляров форм
- Проверка набора форм
- Проверка количества форм в наборе форм
- Работа с заказом и удалением форм
- Добавление дополнительных полей в набор форм
- Передача пользовательских параметров в формы набора форм
- Настройка префикса набора форм
- Использование набора форм в представлениях и шаблонах
- Создание форм из моделей
- Активы формы (
Media
класс)
Смотрите также
- Справка по формам
- Содержит полную справку по API, включая поля форм, виджеты форм, а также проверку форм и полей.