API форм
О документе
Этот документ описывает подробности API форм Django. Сначала следует прочитать введение в работу с формами.
Связанные и несвязанные формы
Экземпляр Form может быть связан с набором данных или несвязан.
- Если он связан с набором данных, он может проверить эти данные и отобразить форму в HTML с отображением данных в HTML.
- Если он несвязан, он не может выполнить проверку (потому что нет данных для проверки!), но он по-прежнему может отобразить пустую форму в HTML.
-
class Form
Чтобы создать экземпляр несвязанной Form, создайте экземпляр класса:
>>> f = ContactForm()
Чтобы связать данные с формой, передайте данные как словарь в качестве первого параметра конструктору класса Form:
>>> data = {'subject': 'hello',
... 'message': 'Hi there',
... 'sender': 'foo@example.com',
... '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, если необходимо добавить пользовательскую проверку для взаимозависимых полей. См. Очистка и проверка взаимозависимых полей для примера использования.
-
Form.is_valid()
Основная задача объекта Form — проверка данных. Для связанного экземпляра Form вызовите метод is_valid() для выполнения проверки и получения логического значения, указывающего, были ли данные валидны:
>>> data = {'subject': 'hello',
... 'message': 'Hi there',
... 'sender': 'foo@example.com',
... '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.
Процедуры проверки будут вызваны только один раз, независимо от того, сколько раз вы получите доступ к errors или вызовете is_valid(). Это означает, что если проверка имеет побочные эффекты, эти побочные эффекты будут вызваны только один раз.
-
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=False)
Возвращает сериализованные ошибки в формате 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 с помощью element.textContent = errorText или с помощью jQuery $(el).text(errorText) (а не его функции .html()).
Если по какой-либо причине вы не хотите использовать экранирование на стороне клиента, вы также можете установить escape_html=True, и сообщения об ошибках будут экранированы, так что вы можете использовать их непосредственно в HTML.
-
Form.errors.get_json_data(escape_html=False)
Возвращает ошибки в виде словаря, подходящего для сериализации в JSON. Form.errors.as_json() возвращает сериализованный JSON, а это — данные ошибки до сериализации.
Параметр escape_html ведёт себя так же, как описано в Form.errors.as_json().
-
Form.add_error(field, error)
Этот метод позволяет добавлять ошибки к определённым полям изнутри метода Form.clean(), или извне формы; например, из представления.
Аргумент field — это имя поля, к которому следует добавить ошибки. Если его значение None, ошибка будет обработана как ошибка вне поля, возвращаемая методом Form.non_field_errors().
Аргумент error может быть строкой или, что предпочтительнее, экземпляром ValidationError. См. Поднятие ValidationError для рекомендаций по определению ошибок формы.
Обратите внимание, что Form.add_error() автоматически удаляет соответствующее поле из cleaned_data.
-
Form.has_error(field, code=None)
Этот метод возвращает логическое значение, указывающее, содержит ли поле ошибку с указанной ошибкой code. Если code равно None, он вернёт True, если поле содержит какие-либо ошибки.
Для проверки ошибок вне поля используйте NON_FIELD_ERRORS в качестве параметра field.
-
Form.non_field_errors()
Этот метод возвращает список ошибок из Form.errors, которые не связаны с конкретным полем. Это включает ошибки, которые возникают в 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 при создании объекта Form, то последнее 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(field, field_name)
Возвращает начальные данные для поля формы. Сначала ищет данные в Form.initial, если они присутствуют, в противном случае пытается получить их из Field.initial. Значения-вызовы вычисляются.
Рекомендуется использовать BoundField.initial вместо get_initial_for_field(), потому что BoundField.initial имеет более простой интерфейс. Кроме того, в отличие от get_initial_for_field(), BoundField.initial кеширует свои значения. Это особенно полезно при работе с вызовами, значения возвращаемых которых могут изменяться (например, datetime.now или uuid.uuid4):
>>> import uuid
>>> class UUIDCommentForm(CommentForm):
... identifier = forms.UUIDField(initial=uuid.uuid4)
>>> f = UUIDCommentForm()
>>> f.get_initial_for_field(f.fields['identifier'], 'identifier')
UUID('972ca9e4-7bfe-4f5b-af7d-07b3aa306334')
>>> f.get_initial_for_field(f.fields['identifier'], 'identifier')
UUID('1b411fab-844e-4dec-bd4f-e9b0495f04d0')
>>> # Using BoundField.initial, for comparison
>>> f['identifier'].initial
UUID('28a09c59-5f00-4ed9-9179-a3b074fa9c30')
>>> f['identifier'].initial
UUID('28a09c59-5f00-4ed9-9179-a3b074fa9c30')
Проверка изменения данных формы
-
Form.has_changed()
Используйте метод has_changed() на вашей Form форме, когда вам нужно проверить, были ли изменены данные формы по сравнению с начальными данными.
>>> data = {'subject': 'hello',
... 'message': 'Hi there',
... 'sender': 'foo@example.com',
... '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': 'foo@example.com',
... 'cc_myself': True}
>>> f = ContactForm(data)
>>> f.is_valid()
True
>>> f.cleaned_data
{'cc_myself': True, 'message': 'Hi there', 'sender': 'foo@example.com', '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 всегда будет содержать только ключ для полей, определённых в Form, даже если вы передали дополнительные данные при определении Form. В этом примере мы передаём кучу дополнительных полей конструктору ContactForm, но cleaned_data содержит только поля формы:
>>> data = {'subject': 'hello',
... 'message': 'Hi there',
... 'sender': 'foo@example.com',
... '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': 'foo@example.com', 'subject': 'hello'}
Если Form валиден, 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 будут соответствующим образом отображены эти данные. Например, если поле представлено <input type="text">, данные будут в атрибуте value. Если поле представлено <input type="checkbox">, тогда этот HTML будет включать checked, если это необходимо:
>>> data = {'subject': 'hello',
... 'message': 'Hi there',
... 'sender': 'foo@example.com',
... '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="foo@example.com" 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представлен тегом<input type="text">, аEmailField—<input type="email">.BooleanField(null=False)представлен тегом<input type="checkbox">. Обратите внимание, что это просто удобные значения по умолчанию; вы можете указать, какой HTML использовать для заданного поля, используя виджеты, о которых мы расскажем в ближайшее время. - HTML-тег
nameдля каждого тега взят непосредственно из имени атрибута в классеContactForm. - Текст метки для каждого поля — например,
'Subject:','Message:'и'Cc myself:'— генерируется из имени поля путём преобразования всех подчёркиваний в пробелы и заглавной буквы первой буквы. Опять же, это просто удобные значения по умолчанию; вы также можете указать метки вручную. - Каждая метка окружена HTML-тегом
<label>, который указывает на соответствующее поле формы через егоid. В свою очередь, егоidгенерируется путём добавления префикса'id_'к имени поля. Атрибутыidи теги<label>включаются в вывод по умолчанию, чтобы следовать лучшим практикам, но вы можете изменить это поведение. - Вывод использует синтаксис HTML5, нацеленный на
<!DOCTYPE html>. Например, он использует булевы атрибуты, такие какchecked, а не стиль XHTMLchecked='checked'.
Хотя <table> — это стандартный стиль вывода, когда вы отображаете форму, доступны и другие стили вывода. Каждый стиль доступен в виде метода объекта формы, и каждый метод рендеринга возвращает строку.
template_name
-
Form.template_name
Имя шаблона, который будет отображаться, если форма преобразуется в строку, например, посредством print(form) или в шаблоне с помощью {{ form }}. По умолчанию это шаблон 'django/forms/default.html', который является псевдонимом для 'django/forms/table.html'. Шаблон может быть изменён для каждой формы путём переопределения атрибута template_name или более общим образом путём переопределения шаблона по умолчанию, см. также Переопределение встроенных шаблонов форм.
template_name_label
-
Form.template_name_label
Шаблон, используемый для рендеринга <label>, поля, используется при вызове BoundField.label_tag(). Может быть изменён для каждой формы путём переопределения этого атрибута или, более общим образом, путём переопределения шаблона по умолчанию, см. также Переопределение встроенных шаблонов форм.
as_p()
-
Form.as_p()
as_p() отображает форму, используя шаблон, назначенный атрибуту формы template_name_p, по умолчанию этот шаблон 'django/forms/p.html'. Этот шаблон отображает форму в виде набора тегов <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() отображает форму, используя шаблон, назначенный атрибуту формы template_name_ul, по умолчанию этот шаблон 'django/forms/ul.html'. Этот шаблон отображает форму в виде набора тегов <li>, где каждый <li> содержит одно поле. Он не включает <ul> или </ul>, чтобы вы могли указать любые атрибуты HTML в теге <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() отображает форму, используя шаблон, назначенный атрибуту формы template_name_table, по умолчанию этот шаблон 'django/forms/table.html'. Этот шаблон выводит форму в виде HTML <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>
get_context()
-
Form.get_context()
Возвращает контекст для рендеринга формы в шаблоне.
Доступный контекст:
-
form: Связанная форма. -
fields: Все связанные поля, кроме скрытых. -
hidden_fields: Все связанные скрытые поля. -
errors: Все ошибки формы, не связанные с полями или скрытыми полями.
render()
-
Form.render(template_name=None, context=None, renderer=None)
Метод render вызывается __str__, а также методами Form.as_table(), Form.as_p() и Form.as_ul(). Все аргументы являются необязательными и по умолчанию:
-
template_name:Form.template_name -
context: Значение, возвращаемоеForm.get_context() -
renderer: Значение, возвращаемоеForm.default_renderer
Стилевое оформление обязательных или с ошибками строк формы
-
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>
Настройка атрибутов HTML элементов формы и тегов метки
-
Form.auto_id
По умолчанию методы рендеринга формы включают:
- Атрибуты HTML
idдля элементов формы. - Соответствующие теги
<label>вокруг меток. Тег HTML<label>указывает, какой текст метки связан с каким элементом формы. Это небольшое улучшение делает формы более удобными и доступными для устройств с вспомогательными технологиями. Всегда рекомендуется использовать теги<label>.
Значения атрибута id генерируются путём добавления префикса id_ к именам полей формы. Однако это поведение можно настроить, если вы хотите изменить соглашение id или полностью удалить атрибуты HTML id и теги <label>.
Используйте аргумент auto_id конструктора Form для управления поведением id и меток. Этот аргумент должен быть True, False или строкой.
Если auto_id равно False, то выходные данные формы не будут содержать тегов <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, выходные данные формы будут содержать теги <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', то выходные данные формы будут содержать теги <label>, и будут генерировать атрибуты id на основе строки формата. Например, для строки формата 'field_%s', поле с именем subject получит значение id 'field_subject'. Продолжая наш пример:
>>> 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 установлено на любое другое истинное значение (например, строка, не содержащая %s), то библиотека будет действовать так, как будто auto_id равно True.
По умолчанию auto_id установлено в строку 'id_%s'.
-
Form.label_suffix
Переводимая строка (по умолчанию двоеточие (:) на английском языке), которая будет добавляться после имени любой метки при рендеринге формы.
Можно настроить этот символ или вообще его опустить, используя параметр 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-вывод будет включать ошибки валидации в виде <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>
Настройка формата списка ошибок
-
class ErrorList(initlist=None, error_class=None, renderer=None) -
По умолчанию формы используют
django.forms.utils.ErrorListдля форматирования ошибок валидации.ErrorList— это объект, похожий на список, гдеinitlist— список ошибок. Кроме того, у этого класса есть следующие атрибуты и методы.-
error_class -
Классы CSS, которые будут использоваться при отображении списка ошибок. Все предоставленные классы добавляются к стандартному классу
errorlist.
-
renderer -
Новое в Django 4.0.
Указывает рендерер для использования при отображении
ErrorList. По умолчанию устанавливается наNone, что означает использование стандартного рендерера, указанного настройкойFORM_RENDERER.
-
template_name -
Новое в Django 4.0.
Имя шаблона, используемого при вызове
__str__илиrender(). По умолчанию это'django/forms/errors/list/default.html', что является псевдонимом для шаблона'ul.html'.
-
template_name_text -
Новое в Django 4.0.
Имя шаблона, используемого при вызове
as_text(). По умолчанию это'django/forms/errors/list/text.html'. Этот шаблон отображает ошибки в виде списка с отступами.
-
template_name_ul -
Новое в Django 4.0.
Имя шаблона, используемого при вызове
as_ul(). По умолчанию это'django/forms/errors/list/ul.html'. Этот шаблон отображает ошибки в тэгах<li>, с обертывающим тэгом<ul>с классами CSS, определёнными вerror_class.
-
get_context() -
Новое в Django 4.0.
Возвращает контекст для отображения ошибок в шаблоне.
Доступный контекст:
-
errors: Список ошибок. -
error_class: Строка классов CSS.
-
-
render(template_name=None, context=None, renderer=None) -
Новое в Django 4.0.
Метод render вызывается
__str__а также методомas_ul().Все аргументы необязательны и будут иметь значения по умолчанию:
-
template_name: Значение, возвращаемоеtemplate_name -
context: Значение, возвращаемоеget_context() -
renderer: Значение, возвращаемоеrenderer
-
-
as_text() -
Отображает список ошибок, используя шаблон, определённый в
template_name_text.
-
as_ul() -
Отображает список ошибок, используя шаблон, определённый в
template_name_ul.
Если вам нужно настроить отображение ошибок, это можно сделать, переопределив атрибут
template_nameили, более общим способом, переопределив стандартный шаблон. См. также Переопределение встроенных шаблонов форм. -
Вывод ErrorList был перенесён в движок шаблонов.
Устарело начиная с версии 4.0: Возможность возвращать str при вызове метода __str__ устарела. Используйте вместо этого движок шаблонов, который возвращает SafeString.
Более подробный вывод
Методы as_p(), as_ul(), и as_table() — это сокращения; они не единственный способ отображения объекта формы.
-
class 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">
Вывод для конкретного поля учитывает настройку объекта формы 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.help_text -
Свойство
help_textполя.
-
BoundField.html_name -
Имя, которое будет использоваться в атрибуте HTML виджета
name. Оно учитываетprefix.
-
BoundField.id_for_label -
Используйте это свойство для отображения ID этого поля. Например, если вы вручную создаёте
<label>в своём шаблоне (несмотря на то, чтоlabel_tag()сделает это за вас):<label for="{{ form.my_field.id_for_label }}">...</label>{{ my_field }}По умолчанию это будет имя поля, префикс
id_(«id_my_field» для приведённого выше примера). Вы можете изменить ID, установивattrsна виджете поля. Например, объявляя поле так:my_field = forms.CharField(widget=forms.TextInput(attrs={'id': 'myFIELD'}))и используя приведенный выше шаблон, будет отображаться что-то вроде:
<label for="myFIELD">...</label><input id="myFIELD" type="text" name="my_field" required>
-
BoundField.initial -
Используйте
BoundField.initial, чтобы получить начальные данные для поля формы. Оно извлекает данные изForm.initial, если оно присутствует, в противном случае пытается получить изField.initial. Значения-вызовы вычисляются. Смотрите Начальные значения формы для получения дополнительных примеров.BoundField.initialкэширует своё возвращаемое значение, что полезно, особенно при работе с вызовами, возвращаемые значения которых могут меняться (например,datetime.nowилиuuid.uuid4):>>> from datetime import datetime >>> class DatedCommentForm(CommentForm): ... created = forms.DateTimeField(initial=datetime.now) >>> f = DatedCommentForm() >>> f['created'].initial datetime.datetime(2021, 7, 27, 9, 5, 54) >>> f['created'].initial datetime.datetime(2021, 7, 27, 9, 5, 54)
Рекомендуется использовать
BoundField.initialвместоget_initial_for_field().
-
Возвращает
Trueесли виджет этогоBoundFieldскрыт.
-
BoundField.label -
Метка поля
label. Используется вlabel_tag().
-
BoundField.name -
Имя этого поля в форме:
>>> f = ContactForm() >>> print(f['subject'].name) subject >>> print(f['message'].name) message
-
BoundField.widget_type -
Возвращает имя класса обернутого виджета поля в нижнем регистре, с удалением любых последующих
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().Этот метод в основном используется во внутренних целях. Следует использовать виджет вместо него.
-
BoundField.as_widget(widget=None, attrs=None, only_initial=False) -
Отображает поле, отображая переданный виджет, добавляя любые атрибуты HTML, переданные как
attrs. Если виджет не указан, используется стандартный виджет поля.only_initialиспользуется внутренними механизмами Django и не следует устанавливать явно.
-
BoundField.css_classes(extra_classes=None) -
При использовании готовых шаблонов 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(contents=None, attrs=None, label_suffix=None) -
Отображает тег метки для поля формы, используя шаблон, указанный в
Form.template_name_label.Доступный контекст:
-
field: Этот экземплярBoundField. -
contents: По умолчанию, конкатенированная строка изBoundField.labelиForm.label_suffix(илиField.label_suffix, если установлено). Может быть переопределено с помощью аргументовcontentsиlabel_suffix. -
attrs: Словарь, содержащийdict,Form.required_css_class, иid.idгенерируется виджетом поляattrsилиBoundField.auto_id. Дополнительные атрибуты могут быть заданы аргументомattrs. -
use_tag: Логическое значение, равноеTrueесли у метки естьid. ЕслиFalse, шаблон по умолчанию пропускает тег<label>.
Подсказка
В вашем шаблоне
field— это экземплярBoundField. Следовательно,field.fieldобращается кBoundField.field, являющемуся объявленным вами полем, напримерforms.CharField.Для отдельного рендеринга тега метки поля формы можно вызвать метод
label_tag():>>> f = ContactForm(data={'message': ''}) >>> print(f['message'].label_tag()) <label for="id_message">Message:</label>Для настройки рендеринга можно переопределить атрибут
Form.template_name_labelили, более общим образом, переопределить шаблон по умолчанию, см. также Переопределение встроенных шаблонов форм.Изменено в Django 4.0:Метка теперь рендерится с помощью движка шаблонов.
-
-
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, field_name) -
Принимает экземпляр
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': 'foo@example.com',
... '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()
Проверка на multipart формы
-
Form.is_multipart()
Если вы пишете многократно используемые представления или шаблоны, вам, возможно, не известно заранее, является ли ваша форма multipart формой или нет. Метод is_multipart() сообщает вам, требует ли форма кодирование 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
Вы можете поместить несколько Django форм внутри одного тега <form>. Для присвоения каждому Form собственного пространства имён используйте аргумент 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'
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/4.0/ref/forms/api/