API форм ¶
Об этом документе
Этот документ подробно описывает Django Forms API. Рекомендуется сначала прочитать введение в использование форм .
Связанные и несвязанные формы ¶
Экземпляр Form
либо привязан (привязан) к набору данных, либо не привязан (не привязан).
- Если он связан с набором данных, он может проверить эти данные и отобразить форму в HTML, включая данные.
- Если он не привязан , он не может проверить (потому что нет данных для проверки!), Но он все равно может отображать пустую HTML-форму.
-
класс
Form
¶
Чтобы создать Form
несвязанный экземпляр , создайте экземпляр класса:
>>> f = ContactForm()
Чтобы привязать данные к форме, передайте эти данные в виде словаря в качестве первого параметра конструктору класса Form
:
>>> data = {'subject': 'hello',
... 'message': 'Hi there',
... 'sender': '[email protected]',
... 'cc_myself': True}
>>> f = ContactForm(data)
В этом словаре ключи - это имена полей, которые соответствуют атрибутам класса Form
. Значения - это данные, которые вы хотите проверить. В принципе, это строки, но это не обязательно. Тип передаваемых данных зависит от поля Field
, как мы сейчас увидим.
-
Form.
is_bound
¶
Если вам нужно различать экземпляры связанных и несвязанных форм во время выполнения, вы можете положиться на атрибут is_bound
формы:
>>> f = ContactForm()
>>> f.is_bound
False
>>> f = ContactForm({'subject': 'hello'})
>>> f.is_bound
True
Обратите внимание, что передача пустого словаря создает связанную форму с пустыми данными:
>>> f = ContactForm({})
>>> f.is_bound
True
Если вы хотите каким-либо образом изменить данные в Form
связанном экземпляре или если вы хотите связать Form
несвязанный экземпляр с некоторыми данными, создайте новый экземпляр Form
. Изменить данные в экземпляре невозможно Form
. После создания экземпляра Form
его данные следует считать неизменными, независимо от того, существуют они или нет.
Использование форм для проверки данных ¶
-
Form.
clean
() ¶
Реализация метода clean()
для формы оправдана, когда для взаимозависимых полей необходима настраиваемая проверка. См. Примеры использования в разделе Очистка и проверка зависимых полей .
-
Form.
is_valid
() ¶
Основная задача объекта Form
- проверка данных. Имея Form
связанный экземпляр , вызовите метод, is_valid()
чтобы выполнить проверку и вернуть логическое значение, указывающее, действительны ли данные:
>>> data = {'subject': 'hello',
... 'message': 'Hi there',
... 'sender': '[email protected]',
... 'cc_myself': True}
>>> f = ContactForm(data)
>>> f.is_valid()
True
Попробуем с некоторыми неверными данными. В этом случае subject
пусто (что является ошибкой, поскольку все поля по умолчанию обязательны) и sender
не является действительным адресом электронной почты:
>>> data = {'subject': '',
... 'message': 'Hi there',
... 'sender': 'invalid email address',
... 'cc_myself': True}
>>> f = ContactForm(data)
>>> f.is_valid()
False
-
Form.
errors
¶
Получите доступ к атрибуту, errors
чтобы получить словарь сообщений об ошибках:
>>> f.errors
{'sender': ['Enter a valid email address.'], 'subject': ['This field is required.']}
В этом словаре ключи соответствуют именам полей, а значения - спискам строк, представляющих сообщения об ошибках. Они хранятся в списках, потому что одно поле может генерировать несколько сообщений об ошибках.
Вы можете получить доступ errors
без предварительного звонка is_valid()
. Данные формы будут проверены во время первого вызова is_valid()
или первого доступа к errors
.
Процедуры проверки вызываются только один раз, даже если вы вызываете несколько раз is_valid()
или выполняете доступ errors
. Это означает, что если проверка вызывает побочные эффекты, они возникают только один раз.
-
Form.errors.
as_data
() ¶
Возвращает словарь, соответствующий полям их ValidationError
исходному экземпляру .
>>> f.errors.as_data()
{'sender': [ValidationError(['Enter a valid email address.'])],
'subject': [ValidationError(['This field is required.'])]}
Используйте этот метод всякий раз, когда необходимо определить ошибку по звуку code
. Это позволяет делать такие вещи, как переписывание сообщения об ошибке или запись собственной логики в представление при наличии данной ошибки. Его также можно использовать для сериализации ошибок в настраиваемом формате (например, XML); например, as_json()
основан на as_data()
.
Необходимость метода as_data()
объясняется обратной совместимостью. Ранее случаи ValidationError
были потеряны момент их сообщения об ошибках были добавлены в их оказанном состоянии в словарь Form.errors
. В идеале Form.errors
пришлось бы хранить экземпляры, ValidationError
а методы с префиксом as_
могли произвести их окончательный рендеринг, но необходимо было действовать в обратном порядке, чтобы не нарушить код, который ожидал найти «окончательные» сообщения об ошибках. в Form.errors
.
-
Form.errors.
as_json
( escape_html = Ложь ) ¶
Возвращать ошибки, сериализованные как JSON.
>>> f.errors.as_json()
{"sender": [{"message": "Enter a valid email address.", "code": "invalid"}],
"subject": [{"message": "This field is required.", "code": "required"}]}
По умолчанию as_json()
не экранировать его содержимое. Если вы используете его в контексте, например, в запросах AJAX к представлению формы, где клиент интерпретирует ответ и вставляет ошибки на страницу, вам нужно обязательно экранировать содержимое на стороне клиента, чтобы избежать возможности атака с использованием межсайтовых сценариев. Вы можете сделать это в JavaScript с помощью или в jQuery с (а не его функцией ).element.textContent = errorText
$(el).text(errorText)
.html()
Если по какой-то причине вы не хотите использовать экранирование на стороне клиента, вы также можете установить, escape_html=True
и сообщения об ошибках будут экранированы, чтобы вы могли использовать их непосредственно в HTML.
-
Form.errors.
get_json_data
( escape_html = Ложь ) ¶
Возвращать ошибки в виде словаря, готового к сериализации в JSON. Form.errors.as_json()
возвращает сериализованный JSON, а этот метод возвращает данные об ошибках перед сериализацией.
Параметр escape_html
имеет такое же поведение, как и для Form.errors.as_json()
.
-
Form.
add_error
( поле , ошибка ) ¶
Этот метод позволяет вам добавлять ошибки в определенные поля из самого метода Form.clean()
или напрямую извне формы, например, из представления.
Параметр field
- это имя поля, которому будут присвоены ошибки. Если его значение равно None
, ошибка рассматривается как ошибка, не связанная с полем, и будет одной из ошибок, возвращаемых функцией Form.non_field_errors()
.
Параметр error
может быть строкой или, предпочтительно, экземпляром ValidationError
. См. Раздел « Создание ValidationError» для получения рекомендаций по определению ошибок формы.
Обратите внимание, что Form.add_error()
автоматически удаляет соответствующие поля из словаря cleaned_data
.
-
Form.
has_error
( поле , код = Нет ) ¶
Этот метод возвращает логическое значение, указывающее, содержит ли поле ошибку с code
определенной ошибкой. Если code
есть None
, метод возвращается, True
если поле содержит ошибку.
Чтобы проверить наличие ошибок, не связанных с полями, укажите NON_FIELD_ERRORS
в параметре field
.
-
Form.
non_field_errors
() ¶
Этот метод возвращает список ошибок Form.errors
, не связанных с определенным полем. Сюда входят ошибки ValidationError
, которые генерируются Form.clean()
и добавляются .Form.add_error(None, "...")
Поведение неродственных форм ¶
Нет причин хотеть проверять форму без данных, но, мягко говоря, вот что происходит с несвязанными формами:
>>> f = ContactForm()
>>> f.is_valid()
False
>>> f.errors
{}
Динамические начальные значения ¶
-
Form.
initial
¶
Параметр initial
используется для объявления начальных значений полей формы во время выполнения. Например, может быть интересно предварительно заполнить поле username
именем пользователя текущего сеанса.
Для этого используйте параметр initial
экземпляра Form
. Если этот параметр присутствует, он должен быть словарем, сопоставляющим имена полей с начальными значениями. Включите только те поля, для которых существует начальное значение; необязательно включать все поля формы. Например :
>>> f = ContactForm(initial={'subject': 'Hi there!'})
Эти значения отображаются только для несвязанных форм и не используются для предоставления значений по умолчанию, если определенное поле остается пустым.
Если поле Field
определено и вы включаете его при создании формы, последнее имеет приоритет. В этом примере заполняется как на уровне поля, так и на уровне экземпляра формы, и последний имеет приоритет:initial
initial
initial
>>> from django import forms
>>> class CommentForm(forms.Form):
... name = forms.CharField(initial='class')
... url = forms.URLField()
... comment = forms.CharField()
>>> f = CommentForm(initial={'name': 'instance'}, auto_id=False)
>>> print(f)
<tr><th>Name:</th><td><input type="text" name="name" value="instance" required></td></tr>
<tr><th>Url:</th><td><input type="url" name="url" required></td></tr>
<tr><th>Comment:</th><td><input type="text" name="comment" required></td></tr>
-
Form.
get_initial_for_field
( поле , имя_поля ) ¶
Используется get_initial_for_field()
для получения исходных данных для поля формы. Данные берутся в Form.initial
и Field.initial
, в таком порядке, и оценивают любое исполняемое начальное значение, если таковые имеются.
Проверка измененных данных формы ¶
-
Form.
has_changed
() ¶
Если вам нужно узнать, какие данные формы были изменены по отношению к исходным данным, используйте метод has_changed()
формы.
>>> data = {'subject': 'hello',
... 'message': 'Hi there',
... 'sender': '[email protected]',
... 'cc_myself': True}
>>> f = ContactForm(data, initial=data)
>>> f.has_changed()
False
Когда форма отправляется, она перестраивается и предоставляются исходные данные, чтобы можно было провести сравнение:
>>> f = ContactForm(request.POST, initial=data)
>>> f.has_changed()
has_changed()
возвращается, True
если данные request.POST
отличаются от того, что было предоставлено, в initial
противном случае возвращается False
. Результат получается путем вызова Field.has_changed()
каждого поля формы.
-
Form.
changed_data
¶
Атрибут changed_data
возвращает список имен полей, значения которых в данных с привязкой к форме (обычно request.POST
) отличаются от тех, которые изначально были предоставлены в initial
. Возвращенный список пуст, если данные полностью идентичны.
>>> f = ContactForm(request.POST, initial=data)
>>> if f.has_changed():
... print("The following fields changed: %s" % ", ".join(f.changed_data))
>>> f.changed_data
['subject', 'message']
Доступ к полям из формы ¶
-
Form.
fields
¶
Вы можете получить доступ к полям экземпляра Form
из его атрибута fields
:
>>> for row in f.fields.values(): print(row)
...
<django.forms.fields.CharField object at 0x7ffaac632510>
<django.forms.fields.URLField object at 0x7ffaac632f90>
<django.forms.fields.CharField object at 0x7ffaac3aa050>
>>> f.fields['name']
<django.forms.fields.CharField object at 0x7ffaac6324d0>
Вы можете редактировать поле в экземпляре, Form
чтобы изменить способ его отображения в форме:
>>> f.as_table().split('\n')[0]
'<tr><th>Name:</th><td><input name="name" type="text" value="instance" required></td></tr>'
>>> f.fields['name'].label = "Username"
>>> f.as_table().split('\n')[0]
'<tr><th>Username:</th><td><input name="name" type="text" value="instance" required></td></tr>'
Будьте осторожны, чтобы не изменить атрибут, так base_fields
как это изменение повлияет на все ContactForm
следующие экземпляры внутри одного процесса Python:
>>> f.base_fields['name'].label = "Username"
>>> another_f = CommentForm(auto_id=False)
>>> another_f.as_table().split('\n')[0]
'<tr><th>Username:</th><td><input name="name" type="text" value="class" required></td></tr>'
Доступ к «очищенным» данным ¶
-
Form.
cleaned_data
¶
Каждое поле класса Form
отвечает не только за проверку своих данных, но и за их «очистку», то есть их нормализацию в согласованном формате. Это очень полезная функция, поскольку она позволяет вводить данные поля несколькими способами, сохраняя при этом согласованность полученных данных.
Например, DateField
нормализует ввод в объект Python datetime.date
. Независимо от того, является ли передаваемый контент строкой формата '1994-07-15'
, объектом datetime.date
или каким-либо другим форматом, он DateField
всегда будет превращать этот контент в объект datetime.date
, пока он действителен.
После создания экземпляра Form
с набором данных и его проверки можно получить доступ к очищенным данным по их атрибуту cleaned_data
:
>>> data = {'subject': 'hello',
... 'message': 'Hi there',
... 'sender': '[email protected]',
... 'cc_myself': True}
>>> f = ContactForm(data)
>>> f.is_valid()
True
>>> f.cleaned_data
{'cc_myself': True, 'message': 'Hi there', 'sender': '[email protected]', 'subject': 'hello'}
Обратите внимание, что любое текстовое поле, такое как CharField
или EmailField
, всегда очищает типизированное содержимое, превращая его в строку. Мы обсудим последствия кодирования позже в этом документе.
Если ваши данные не все действительны, словарь cleaned_data
содержит только допустимые поля:
>>> data = {'subject': '',
... 'message': 'Hi there',
... 'sender': 'invalid email address',
... 'cc_myself': True}
>>> f = ContactForm(data)
>>> f.is_valid()
False
>>> f.cleaned_data
{'cc_myself': True, 'message': 'Hi there'}
cleaned_data
всегда содержит только ключи, соответствующие полям, определенным в форме, даже если вы передаете ему дополнительные данные при создании формы. В этом примере мы передаем конструктору дополнительные данные поля ContactForm
, но они cleaned_data
содержат только те данные, которые соответствуют полям в форме:
>>> data = {'subject': 'hello',
... 'message': 'Hi there',
... 'sender': '[email protected]',
... 'cc_myself': True,
... 'extra_field_1': 'foo',
... 'extra_field_2': 'bar',
... 'extra_field_3': 'baz'}
>>> f = ContactForm(data)
>>> f.is_valid()
True
>>> f.cleaned_data # Doesn't contain extra_field_1, etc.
{'cc_myself': True, 'message': 'Hi there', 'sender': '[email protected]', 'subject': 'hello'}
Если форма действительна, cleaned_data
включает ключ и значение для всех своих полей, даже если данные не содержат значения для некоторых дополнительных полей. В этом примере словарь данных не содержит значения для поля nick_name
, но cleaned_data
все равно интегрирует его с пустым значением:
>>> from django import forms
>>> class OptionalPersonForm(forms.Form):
... first_name = forms.CharField()
... last_name = forms.CharField()
... nick_name = forms.CharField(required=False)
>>> data = {'first_name': 'John', 'last_name': 'Lennon'}
>>> f = OptionalPersonForm(data)
>>> f.is_valid()
True
>>> f.cleaned_data
{'nick_name': '', 'first_name': 'John', 'last_name': 'Lennon'}
В приведенном выше примере, значение cleaned_data
из nick_name
является пустой строкой , потому что nick_name
это поле CharField
, и эти поля рассматривать пустую строку как пустое значение. Каждый тип поля знает свое пустое значение, например, DateField
используйте None
вместо пустой строки. Дополнительные сведения о поведении каждого поля в этом сценарии см. В разделе «Пустое значение» для каждого поля в разделе « Field
Встроенные классы» ниже.
Можно написать код для выполнения проверки определенных полей формы (по их имени) или для всей формы (с учетом комбинации различных полей). Дополнительную информацию об этом можно найти в разделе «Проверка форм и полей» .
Отображение форм в HTML ¶
Вторая задача объекта Form
- отобразить себя в формате HTML. Для этого отобразите его с помощью print
:
>>> f = ContactForm()
>>> print(f)
<tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" required></td></tr>
<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" required></td></tr>
<tr><th><label for="id_sender">Sender:</label></th><td><input type="email" name="sender" id="id_sender" required></td></tr>
<tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself"></td></tr>
Если форма привязана к данным, вывод HTML будет содержать эти данные должным образом. Например, если поле представлено компонентом , данные появятся в атрибуте . Если поле представлено компонентом , созданный HTML-код будет содержать, если применимо:<input type="text">
value
<input type="checkbox">
checked
>>> data = {'subject': 'hello',
... 'message': 'Hi there',
... 'sender': '[email protected]',
... 'cc_myself': True}
>>> f = ContactForm(data)
>>> print(f)
<tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" value="hello" required></td></tr>
<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" value="Hi there" required></td></tr>
<tr><th><label for="id_sender">Sender:</label></th><td><input type="email" name="sender" id="id_sender" value="[email protected]" required></td></tr>
<tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" checked></td></tr>
Этот вывод по умолчанию представляет собой HTML-таблицу с двумя столбцами, по одной строке <tr>
на поле. Обратите внимание на это:
- По маневренности причин результат не не содержит
<table>
и тег</table>
, ни<form>
,</form>
или меток . Вы должны их предоставить.<input type="submit">
- Каждый тип элемента управления имеет представление HTML по умолчанию.
CharField
представлена и с помощью . представлен . Обратите внимание, что это только разумные значения по умолчанию; можно определить HTML-код, создаваемый конкретным полем, с помощью компонентов, которые мы объясним позже.<input type="text">
EmailField
<input type="email">
BooleanField(null=False)
<input type="checkbox">
name
HTML- имя каждого тега напрямую выводится из имени его атрибута в классеContactForm
.- Текстовая метка для каждого поля (например
'Subject:'
,'Message:'
и ) создается из имени поля путем преобразования всех подчеркиваний в пробелы и использования первой буквы с заглавной буквы. Опять же, это просто более или менее адекватные значения по умолчанию; вы также можете определить эти метки вручную.'Cc myself:'
- Каждая текстовая метка встроена в тег HTML,
<label>
который ссылается на свое поле формы по его атрибутуid
. Значение этого параметра создается путем добавления префикса'id_'
к имени поля. Атрибутыid
и теги<label>
включаются в созданный HTML по умолчанию для лучшей практики, но вы можете изменить это поведение. - В результате используется синтаксис HTML5 с заголовком . Например, такие логические атрибуты предпочтительнее стиля XHTML .
<!DOCTYPE html>
checked
checked='checked'
Хотя результат as <table>
является стилем результата по умолчанию при отображении формы с print
, доступны другие стили результата. Каждый стиль доступен для метода объекта формы, и каждый метод отрисовки возвращает строку.
as_p()
¶
-
Form.
as_p
() ¶
as_p()
создает форму с рядом тегов <p>
, каждый из которых содержит поле:
>>> f = ContactForm()
>>> f.as_p()
'<p><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" required></p>\n<p><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" required></p>\n<p><label for="id_sender">Sender:</label> <input type="text" name="sender" id="id_sender" required></p>\n<p><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself"></p>'
>>> print(f.as_p())
<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> <input type="text" name="message" id="id_message" required></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>
as_ul()
¶
-
Form.
as_ul
() ¶
as_ul()
создает форму с серией тегов <li>
, каждый из которых содержит поле. В <ul>
и теги </ul>
не включены, давая вам возможность определить атрибуты тега сами <ul>
:
>>> f = ContactForm()
>>> f.as_ul()
'<li><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" required></li>\n<li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" required></li>\n<li><label for="id_sender">Sender:</label> <input type="email" name="sender" id="id_sender" required></li>\n<li><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself"></li>'
>>> print(f.as_ul())
<li><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" required></li>
<li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" required></li>
<li><label for="id_sender">Sender:</label> <input type="email" name="sender" id="id_sender" required></li>
<li><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself"></li>
as_table()
¶
-
Form.
as_table
() ¶
Наконец, as_table()
создайте форму в теге HTML <table>
. Это тот же результат, что и при его отображении print
. Фактически, когда с ним отображается объект формы print
, его метод as_table()
вызывается в фоновом режиме:
>>> f = ContactForm()
>>> f.as_table()
'<tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" required></td></tr>\n<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" required></td></tr>\n<tr><th><label for="id_sender">Sender:</label></th><td><input type="email" name="sender" id="id_sender" required></td></tr>\n<tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself"></td></tr>'
>>> print(f)
<tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" required></td></tr>
<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" required></td></tr>
<tr><th><label for="id_sender">Sender:</label></th><td><input type="email" name="sender" id="id_sender" required></td></tr>
<tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself"></td></tr>
Добавление стилей в обязательные или ошибочные строки формы ¶
-
Form.
error_css_class
¶
-
Form.
required_css_class
¶
Довольно часто приходится определять определенные стили для строк и полей формы, которые являются обязательными или содержат ошибки. Например, мы можем выделить обязательные строки формы жирным шрифтом, а ошибки - красным.
Класс Form
предлагает несколько точек входа для добавления атрибутов class
в обязательные строки или строки с ошибками: заполните атрибуты Form.error_css_class
иForm.required_css_class
from django import forms
class ContactForm(forms.Form):
error_css_class = 'error'
required_css_class = 'required'
# ... and the rest of your fields here
После этого классы "error"
и "required"
будут присвоены соответствующим строкам. HTML-код будет выглядеть примерно так:
>>> f = ContactForm(data)
>>> print(f.as_table())
<tr class="required"><th><label class="required" for="id_subject">Subject:</label> ...
<tr class="required"><th><label class="required" for="id_message">Message:</label> ...
<tr class="required error"><th><label class="required" for="id_sender">Sender:</label> ...
<tr><th><label for="id_cc_myself">Cc myself:<label> ...
>>> f['subject'].label_tag()
<label class="required" for="id_subject">Subject:</label>
>>> f['subject'].label_tag(attrs={'class': 'foo'})
<label for="id_subject" class="foo required">Subject:</label>
Настройка атрибутов id
и тегов <label>
в HTML форм ¶
-
Form.
auto_id
¶
По умолчанию методы отрисовки HTML для форм включают:
- HTML-атрибуты
id
элементов формы. - Теги
<label>
вокруг меток полей. Тег HTML<label>
определяет, какой описательный текст связан с элементом формы. Это небольшое улучшение делает формы более удобными для пользователя и более приспособленными к методам обеспечения доступности. Рекомендуется всегда использовать теги<label>
.
Значения атрибутов id
создаются путем добавления к именам полей формы префикса id_
. Однако этот механизм можно настроить, если вы хотите изменить соглашение id
или полностью удалить атрибуты id
или теги HTML <label>
.
Используйте параметр auto_id
конструктора Form
для управления поведением id
и label
. Этот параметр должен быть равен True
, False
или содержать строку.
Если auto_id
равно False
, HTML-рендеринг формы не будет содержать никаких тегов <label>
или атрибутов id
:
>>> f = ContactForm(auto_id=False)
>>> print(f.as_table())
<tr><th>Subject:</th><td><input type="text" name="subject" maxlength="100" required></td></tr>
<tr><th>Message:</th><td><input type="text" name="message" required></td></tr>
<tr><th>Sender:</th><td><input type="email" name="sender" required></td></tr>
<tr><th>Cc myself:</th><td><input type="checkbox" name="cc_myself"></td></tr>
>>> print(f.as_ul())
<li>Subject: <input type="text" name="subject" maxlength="100" required></li>
<li>Message: <input type="text" name="message" required></li>
<li>Sender: <input type="email" name="sender" required></li>
<li>Cc myself: <input type="checkbox" name="cc_myself"></li>
>>> print(f.as_p())
<p>Subject: <input type="text" name="subject" maxlength="100" required></p>
<p>Message: <input type="text" name="message" required></p>
<p>Sender: <input type="email" name="sender" required></p>
<p>Cc myself: <input type="checkbox" name="cc_myself"></p>
Если auto_id
установлено значение True
, HTML-рендеринг формы будет содержать теги <label>
и использовать имя поля в качестве идентификатора id
для каждого поля формы:
>>> f = ContactForm(auto_id=True)
>>> print(f.as_table())
<tr><th><label for="subject">Subject:</label></th><td><input id="subject" type="text" name="subject" maxlength="100" required></td></tr>
<tr><th><label for="message">Message:</label></th><td><input type="text" name="message" id="message" required></td></tr>
<tr><th><label for="sender">Sender:</label></th><td><input type="email" name="sender" id="sender" required></td></tr>
<tr><th><label for="cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="cc_myself"></td></tr>
>>> print(f.as_ul())
<li><label for="subject">Subject:</label> <input id="subject" type="text" name="subject" maxlength="100" required></li>
<li><label for="message">Message:</label> <input type="text" name="message" id="message" required></li>
<li><label for="sender">Sender:</label> <input type="email" name="sender" id="sender" required></li>
<li><label for="cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="cc_myself"></li>
>>> print(f.as_p())
<p><label for="subject">Subject:</label> <input id="subject" type="text" name="subject" maxlength="100" required></p>
<p><label for="message">Message:</label> <input type="text" name="message" id="message" required></p>
<p><label for="sender">Sender:</label> <input type="email" name="sender" id="sender" required></p>
<p><label for="cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="cc_myself"></p>
Если auto_id
установлено значение строки, содержащей символ формата '%s'
, HTML-рендеринг формы будет содержать теги <label>
и выходные атрибуты id
на основе строки формата. Например, для строки формата 'champ_%s'
атрибут id
поля с именем «тема» будет 'champ_sujet'
. Продолжая наш пример:
>>> f = ContactForm(auto_id='id_for_%s')
>>> print(f.as_table())
<tr><th><label for="id_for_subject">Subject:</label></th><td><input id="id_for_subject" type="text" name="subject" maxlength="100" required></td></tr>
<tr><th><label for="id_for_message">Message:</label></th><td><input type="text" name="message" id="id_for_message" required></td></tr>
<tr><th><label for="id_for_sender">Sender:</label></th><td><input type="email" name="sender" id="id_for_sender" required></td></tr>
<tr><th><label for="id_for_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_for_cc_myself"></td></tr>
>>> print(f.as_ul())
<li><label for="id_for_subject">Subject:</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" required></li>
<li><label for="id_for_message">Message:</label> <input type="text" name="message" id="id_for_message" required></li>
<li><label for="id_for_sender">Sender:</label> <input type="email" name="sender" id="id_for_sender" required></li>
<li><label for="id_for_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself"></li>
>>> print(f.as_p())
<p><label for="id_for_subject">Subject:</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" required></p>
<p><label for="id_for_message">Message:</label> <input type="text" name="message" id="id_for_message" required></p>
<p><label for="id_for_sender">Sender:</label> <input type="email" name="sender" id="id_for_sender" required></p>
<p><label for="id_for_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself"></p>
Если auto_id
установлено любое другое значение, которое оценивается как «истина», например строка, не содержащая a %s
, библиотека примет auto_id
это значение True
.
По умолчанию auto_id
содержит значение 'id_%s'
.
-
Form.
label_suffix
¶
Переводимая строка (по умолчанию - двоеточие ( :
)), которая будет добавлена к имени каждой метки при визуализации HTML-формы.
Этот символ можно настроить или полностью исключить с помощью параметра label_suffix
:
>>> f = ContactForm(auto_id='id_for_%s', label_suffix='')
>>> print(f.as_ul())
<li><label for="id_for_subject">Subject</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" required></li>
<li><label for="id_for_message">Message</label> <input type="text" name="message" id="id_for_message" required></li>
<li><label for="id_for_sender">Sender</label> <input type="email" name="sender" id="id_for_sender" required></li>
<li><label for="id_for_cc_myself">Cc myself</label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself"></li>
>>> f = ContactForm(auto_id='id_for_%s', label_suffix=' ->')
>>> print(f.as_ul())
<li><label for="id_for_subject">Subject -></label> <input id="id_for_subject" type="text" name="subject" maxlength="100" required></li>
<li><label for="id_for_message">Message -></label> <input type="text" name="message" id="id_for_message" required></li>
<li><label for="id_for_sender">Sender -></label> <input type="email" name="sender" id="id_for_sender" required></li>
<li><label for="id_for_cc_myself">Cc myself -></label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself"></li>
Обратите внимание , что суффикс метки добавляется только если последний символ метки не символ пунктуации (на английском языке это .
, !
, ?
или :
).
Поля также могут определять свои собственные label_suffix
. Это определение имеет приоритет Form.label_suffix
. Суффикс также может быть перегружен во время выполнения с помощью параметра label_suffix
из label_tag()
.
-
Form.
use_required_attribute
¶
Если установлено значение True
(по умолчанию), обязательные поля формы имеют атрибут HTML required
.
В комплекте формы создает свои формы с , use_required_attribute=False
чтобы избежать неправильных браузеров проверки при добавлении или удаления форм в комплекте формы.
Настройка отрисовки компонентов формы ¶
-
Form.
default_renderer
¶
Задает механизм визуализации, используемый для формы. Является ли по None
умолчанию, что означает , что движок рендеринга по умолчанию определяется в настройках FORM_RENDERER
будет использоваться.
Вы можете установить его в качестве атрибута класса при объявлении формы или использовать параметр renderer
в Form.__init__()
. Например :
from django import forms
class MyForm(forms.Form):
default_renderer = MyRenderer()
или :
form = MyForm(renderer=MyRenderer())
Примечания по сортировке полей ¶
В ярлыки as_p()
, as_ul()
и as_table()
, поля отображаются в порядке их определения в классе формы. Например, в примере ContactForm
, поля определены в порядке subject
, message
, sender
, cc_myself
. Чтобы изменить этот порядок в выводе HTML, измените порядок, в котором эти поля появляются в классе.
Есть еще несколько способов изменить этот порядок:
-
Form.
field_order
¶
По умолчанию Form.field_order=None
,, который поддерживает порядок, в котором поля определены в классе формы. Если field_order
это список имен полей, поля упорядочиваются в соответствии с этим списком, а остальные поля добавляются в порядке по умолчанию. Неизвестные имена полей в списке игнорируются. Это позволяет деактивировать поле в подклассе, установив для него значение, None
без необходимости переопределять порядок.
Также можно использовать параметр Form.field_order
класса, Form
чтобы переопределить порядок полей. Если форма Form
наборы и что входит в конкретизации , это последнее , что имеет приоритет.field_order
field_order
Form
field_order
-
Form.
order_fields
( field_order ) ¶
Вы можете изменить порядок полей в любое время, используя order_fields()
список имен полей, как в field_order
.
Просмотр ошибок ¶
Когда вы отображаете объект с Form
привязкой к данным, при его отображении форма будет автоматически проверяться, если она еще не была проверена, а вывод HTML будет содержать ошибки проверки в виде раздела рядом с полем. Точное расположение сообщений об ошибках зависит от используемого метода рендеринга HTML:<ul class="errorlist">
>>> data = {'subject': '',
... 'message': 'Hi there',
... 'sender': 'invalid email address',
... 'cc_myself': True}
>>> f = ContactForm(data, auto_id=False)
>>> print(f.as_table())
<tr><th>Subject:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="subject" maxlength="100" required></td></tr>
<tr><th>Message:</th><td><input type="text" name="message" value="Hi there" required></td></tr>
<tr><th>Sender:</th><td><ul class="errorlist"><li>Enter a valid email address.</li></ul><input type="email" name="sender" value="invalid email address" required></td></tr>
<tr><th>Cc myself:</th><td><input checked type="checkbox" name="cc_myself"></td></tr>
>>> print(f.as_ul())
<li><ul class="errorlist"><li>This field is required.</li></ul>Subject: <input type="text" name="subject" maxlength="100" required></li>
<li>Message: <input type="text" name="message" value="Hi there" required></li>
<li><ul class="errorlist"><li>Enter a valid email address.</li></ul>Sender: <input type="email" name="sender" value="invalid email address" required></li>
<li>Cc myself: <input checked type="checkbox" name="cc_myself"></li>
>>> print(f.as_p())
<p><ul class="errorlist"><li>This field is required.</li></ul></p>
<p>Subject: <input type="text" name="subject" maxlength="100" required></p>
<p>Message: <input type="text" name="message" value="Hi there" required></p>
<p><ul class="errorlist"><li>Enter a valid email address.</li></ul></p>
<p>Sender: <input type="email" name="sender" value="invalid email address" required></p>
<p>Cc myself: <input checked type="checkbox" name="cc_myself"></p>
Настройка формата списка ошибок ¶
По умолчанию формы используют django.forms.utils.ErrorList
для форматирования ошибки проверки. Если вы хотите использовать другой класс для отображения ошибок, вы можете указать это при построении формы.
>>> from django.forms.utils import ErrorList
>>> class DivErrorList(ErrorList):
... def __str__(self):
... return self.as_divs()
... def as_divs(self):
... if not self: return ''
... return '<div class="errorlist">%s</div>' % ''.join(['<div class="error">%s</div>' % e for e in self])
>>> f = ContactForm(data, auto_id=False, error_class=DivErrorList)
>>> f.as_p()
<div class="errorlist"><div class="error">This field is required.</div></div>
<p>Subject: <input type="text" name="subject" maxlength="100" required></p>
<p>Message: <input type="text" name="message" value="Hi there" required></p>
<div class="errorlist"><div class="error">Enter a valid email address.</div></div>
<p>Sender: <input type="email" name="sender" value="invalid email address" required></p>
<p>Cc myself: <input checked type="checkbox" name="cc_myself"></p>
Более тонкий дисплей ¶
Методы as_p()
, as_ul()
и представляют as_table()
собой ярлыки, они не являются единственными способами для отображения объекта формы.
-
класс
BoundField
¶ Используется для отображения в HTML одного поля экземпляра
Form
или для доступа к его атрибутам.Метод
__str__()
этого объекта отображает HTML-код поля.
Чтобы получить один BoundField
, используйте синтаксис поиска по словарю в форме, используя имя поля в качестве ключа:
>>> form = ContactForm()
>>> print(form['subject'])
<input id="id_subject" type="text" name="subject" maxlength="100" required>
Чтобы получить все объекты BoundField
, прокрутите форму:
>>> form = ContactForm()
>>> for boundfield in form: print(boundfield)
<input id="id_subject" type="text" name="subject" maxlength="100" required>
<input type="text" name="message" id="id_message" required>
<input type="email" name="sender" id="id_sender" required>
<input type="checkbox" name="cc_myself" id="id_cc_myself">
Конкретный результат HTML для каждого поля соответствует настройке auto_id
объекта формы:
>>> f = ContactForm(auto_id=False)
>>> print(f['message'])
<input type="text" name="message" required>
>>> f = ContactForm(auto_id='id_%s')
>>> print(f['message'])
<input type="text" name="message" id="id_message" required>
Атрибуты BoundField
¶
-
BoundField.
auto_id
¶ Атрибут HTML ID этого объекта
BoundField
. Возвращает пустую строку , еслиForm.auto_id
естьFalse
.
-
BoundField.
data
¶ Это свойство возвращает данные для этого объекта,
BoundField
полученные методом компонентаvalue_from_datadict()
, илиNone
если он не был указан:>>> unbound_form = ContactForm() >>> print(unbound_form['subject'].data) None >>> bound_form = ContactForm(data={'subject': 'My Subject'}) >>> print(bound_form['subject'].data) My Subject
-
BoundField.
errors
¶ Объект , связанный со списком , который отображается секцией при отображении в HTML:
<ul class="errorlist">
>>> data = {'subject': 'hi', 'message': '', 'sender': '', 'cc_myself': ''} >>> f = ContactForm(data, auto_id=False) >>> print(f['message']) <input type="text" name="message" required> >>> f['message'].errors ['This field is required.'] >>> print(f['message'].errors) <ul class="errorlist"><li>This field is required.</li></ul> >>> f['subject'].errors [] >>> print(f['subject'].errors) >>> str(f['subject'].errors) ''
-
BoundField.
field
¶ Экземпляр
Field
класса формы, которыйBoundField
адаптируется этим объектом .
-
BoundField.
form
¶ Экземпляр,
Form
с которым связан этот объектBoundField
.
-
BoundField.
html_name
¶ Имя, которое будет использоваться в атрибуте
name
HTML-кода компонента. При этом учитывается ценностьprefix
формы.
-
BoundField.
id_for_label
¶ Используйте это свойство, чтобы создать идентификатор для этого поля. Например, если вы вручную создаете тег
<label>
в шаблоне (игнорирование этогоlabel_tag()
подойдет вам):<label for="{{ form.my_field.id_for_label }}">...</label>{{ my_field }}
По умолчанию это будет имя поля с префиксом
id_
(«id_my_field
» в примере выше). Этот идентификатор можно изменить, заполнивattrs
компонент элемента управления. Например, определение такого поля:my_field = forms.CharField(widget=forms.TextInput(attrs={'id': 'myFIELD'}))
и используя шаблон выше, вывод будет примерно таким:
<label for="myFIELD">...</label><input id="myFIELD" type="text" name="my_field" required>
Возвращает
True
, является ли компонент этого объектаBoundField
невидимым.
-
BoundField.
label
¶ Метка
label
поля. Используется в методеlabel_tag()
.
-
BoundField.
name
¶ Имя этого поля в форме:
>>> f = ContactForm() >>> print(f['subject'].name) subject >>> print(f['message'].name) message
-
BoundField.
widget_type
¶ - Новое в Django 3.1.
Возвращает имя класса в нижнем регистре виджета обернутого поля с любыми завершающими
input
илиwidget
удаленными. Это может использоваться при построении форм, где макет зависит от типа виджета. Например:{% for field in form %} {% if field.widget_type == 'checkbox' %} # render one way {% else %} # render another way {% endif %} {% endfor %}
Методы BoundField
¶
Возвращает строку HTML для представления поля как .
<input type="hidden">
**kwargs
ретранслируется вas_widget()
.Этот метод в основном используется внутри компании. Вместо этого лучше использовать компонент (
widget
).
-
BoundField.
as_widget
( widget = None , attrs = None , only_initial = False ) ¶ Производит отображение поля, полагаясь на
widget
переданный компонент и добавляя любые атрибуты HTML, переданные вattrs
. Если компонент не указан, будет использоваться компонент элемента управления по умолчанию.only_initial
используется внутри Django и не должен определяться явно.
-
BoundField.
css_classes
( extra_classes = Нет ) ¶ При использовании ярлыков отображения Django классы CSS используются для обозначения обязательных полей формы или полей с ошибками. Если вы вручную отображаете поля формы, эти классы CSS доступны по методу
css_classes
:>>> f = ContactForm(data={'message': ''}) >>> f['message'].css_classes() 'required'
Если вы хотите предоставить дополнительные классы в дополнение к классам, связанным с ошибками и обязательными полями, можно указать эти классы в качестве параметра:
>>> f = ContactForm(data={'message': ''}) >>> f['message'].css_classes('foo bar') 'foo bar required'
-
BoundField.
label_tag
( Не содержимое = нет , ATTRS = нет , label_suffix = None ) ¶ Чтобы отобразить тег
label
поля формы отдельно , мы можем вызвать его методlabel_tag()
:>>> f = ContactForm(data={'message': ''}) >>> print(f['message'].label_tag()) <label for="id_message">Message:</label>
Можно указать параметр,
contents
который заменитlabel
автоматически сгенерированный тег . Словарьattrs
может содержать дополнительные атрибуты тега<label>
.Сгенерированный HTML-код включает значение
label_suffix
формы (символ двоеточия по умолчанию) или, если определено, значениеlabel_suffix
конкретного поля.label_suffix
Необязательный параметр позволяет вам переопределить любой суффикс, определенный ранее. Например, вы можете использовать пустую строку, чтобы скрыть метку для определенных полей. Если вам нужно сделать это в шаблоне, можно написать собственный фильтр, чтобы вы могли передавать параметры вlabel_tag
.
-
BoundField.
value
() ¶ Используйте этот метод для отображения необработанного значения поля, как если бы оно содержалось в компоненте
Widget
:>>> initial = {'subject': 'welcome'} >>> unbound_form = ContactForm(initial=initial) >>> bound_form = ContactForm(data={'subject': 'hi'}, initial=initial) >>> print(unbound_form['subject'].value()) welcome >>> print(bound_form['subject'].value()) hi
Настройка BoundField
¶
Если вам нужно получить доступ к некоторой дополнительной информации из поля формы в трафарете, и просто использовать подкласс Field
недостаточно, подумайте также о настройке BoundField
.
Поле настраиваемой формы может заменить get_bound_field()
:
-
Field.
get_bound_field
( форма , имя_поля ) ¶ Принимает экземпляр
Form
и имя поля. Возвращенное значение будет использоваться для доступа к полю в шаблоне. Скорее всего, это будет экземпляр подклассаBoundField
.
Если, например, у вас есть поле, GPSCoordinatesField
и вы хотите иметь доступ к дополнительной информации о координатах в шаблоне, это можно реализовать следующим образом:
class GPSCoordinatesBoundField(BoundField):
@property
def country(self):
"""
Return the country the coordinates lie in or None if it can't be
determined.
"""
value = self.value()
if value:
return get_country_from_coordinates(value)
else:
return None
class GPSCoordinatesField(Field):
def get_bound_field(self, form, field_name):
return GPSCoordinatesBoundField(form, self, field_name)
Теперь можно получить доступ к стране в шаблоне с помощью .{{ form.coordinates.country }}
Связывание загруженных файлов с формой ¶
При работе с полями формы типа FileField
или ImageField
все становится немного сложнее.
Во-первых, чтобы иметь возможность отправлять файлы, важно, чтобы тег <form>
формы правильно установил для своего атрибута enctype
значение "multipart/form-data"
:
<form enctype="multipart/form-data" method="post" action="/foo/">
Во-вторых, при создании экземпляра формы вам необходимо связать данные типа файла. Эти данные обрабатываются отдельно от данных обычной формы, поэтому, когда форма содержит поле FileField
или ImageField
, она должна получить второй параметр при связывании формы с данными. Итак, если мы расширим наш, ContactForm
чтобы он содержал ImageField
именованное поле mugshot
, нам нужно связать данные файла, содержащие изображение mugshot
:
# Bound form with an image field
>>> from django.core.files.uploadedfile import SimpleUploadedFile
>>> data = {'subject': 'hello',
... 'message': 'Hi there',
... 'sender': '[email protected]',
... 'cc_myself': True}
>>> file_data = {'mugshot': SimpleUploadedFile('face.jpg', <file data>)}
>>> f = ContactFormWithMugshot(data, file_data)
На практике вы обычно указываете request.FILES
в качестве источника данных файла (как для request.POST
представления источника данных формы):
# Bound form with an image field, data from the request
>>> f = ContactFormWithMugshot(request.POST, request.FILES)
Конструкция несвязанной формы не меняется, просто опускаются как данные формы, так и данные файла:
# Unbound form with an image field
>>> f = ContactFormWithMugshot()
Обнаружение составных форм ¶
-
Form.
is_multipart
() ¶
Если вы пишете многоразовые представления или шаблоны, могут быть случаи, когда заранее неизвестно, является ли форма составной. Метод is_multipart()
указывает, требует ли форма составного кодирования при отправке:
>>> f = ContactFormWithMugshot()
>>> f.is_multipart()
True
Вот пример того, как использовать этот метод в шаблоне:
{% if form.is_multipart %}
<form enctype="multipart/form-data" method="post" action="/foo/">
{% else %}
<form method="post" action="/foo/">
{% endif %}
{{ form }}
</form>
Формы и подклассы ¶
Если у вас есть несколько классов Form
, поля которых являются общими, можно использовать наследование, чтобы избежать избыточности.
При наследовании от Form
настраиваемого класса результирующий подкласс включает все поля из его родительских классов, за которыми следуют поля, определенные в подклассе.
В этом примере ContactFormWithPriority
содержит все поля ContactForm
плюс дополнительное поле priority
. Поля ContactForm
появляются первыми:
>>> class ContactFormWithPriority(ContactForm):
... priority = forms.CharField()
>>> f = ContactFormWithPriority(auto_id=False)
>>> print(f.as_ul())
<li>Subject: <input type="text" name="subject" maxlength="100" required></li>
<li>Message: <input type="text" name="message" required></li>
<li>Sender: <input type="email" name="sender" required></li>
<li>Cc myself: <input type="checkbox" name="cc_myself"></li>
<li>Priority: <input type="text" name="priority" required></li>
Возможно наследование от нескольких форм, считая эти формы «миксинами». В этом примере BeatleForm
наследуется от PersonForm
и InstrumentForm
(в указанном порядке), а его список полей содержит поля от его родительских классов:
>>> from django import forms
>>> class PersonForm(forms.Form):
... first_name = forms.CharField()
... last_name = forms.CharField()
>>> class InstrumentForm(forms.Form):
... instrument = forms.CharField()
>>> class BeatleForm(InstrumentForm, PersonForm):
... haircut_type = forms.CharField()
>>> b = BeatleForm(auto_id=False)
>>> print(b.as_ul())
<li>First name: <input type="text" name="first_name" required></li>
<li>Last name: <input type="text" name="last_name" required></li>
<li>Instrument: <input type="text" name="instrument" required></li>
<li>Haircut type: <input type="text" name="haircut_type" required></li>
Можно декларативно удалить поле, Field
унаследованное от родительского класса, задав его имя None
в подклассе. Например :
>>> from django import forms
>>> class ParentForm(forms.Form):
... name = forms.CharField()
... age = forms.IntegerField()
>>> class ChildForm(ParentForm):
... name = None
>>> list(ChildForm().fields)
['age']
Префиксы форм ¶
-
Form.
prefix
¶
Тег <form>
может содержать несколько форм Django. Чтобы каждая форма имела собственное пространство имен, используйте именованный параметр prefix
:
>>> mother = PersonForm(prefix="mother")
>>> father = PersonForm(prefix="father")
>>> print(mother.as_ul())
<li><label for="id_mother-first_name">First name:</label> <input type="text" name="mother-first_name" id="id_mother-first_name" required></li>
<li><label for="id_mother-last_name">Last name:</label> <input type="text" name="mother-last_name" id="id_mother-last_name" required></li>
>>> print(father.as_ul())
<li><label for="id_father-first_name">First name:</label> <input type="text" name="father-first_name" id="id_father-first_name" required></li>
<li><label for="id_father-last_name">Last name:</label> <input type="text" name="father-last_name" id="id_father-last_name" required></li>
Префикс также можно определить на уровне класса формы:
>>> class PersonForm(forms.Form):
... ...
... prefix = 'person'