API форм
Об этом документе
В этом документе рассматриваются подробности API форм Django. Сначала следует прочитать введение в работу с формами.
Связанные и несвязанные формы
Экземпляр Form либо связан с набором данных, либо не связан.
- Если он связан с набором данных, он может проверить эти данные и отобразить форму в виде 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()
Возвращает dict, сопоставляющий поля с исходными экземплярами 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 или с помощью $(el).text(errorText) из jQuery (а не функции .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, не связанных с конкретным полем. Сюда входят ValidationErrors, возникшие в 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 и при создании экземпляра Form вы указываете 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)
<div>Name:<input type="text" name="name" value="instance" required></div>
<div>Url:<input type="url" name="url" required></div>
<div>Comment:<input type="text" name="comment" required></div>
-
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>
Вы можете изменить поле и BoundField экземпляра Form, чтобы изменить способ его отображения в форме:
>>> f.as_div().split("</div>")[0]
'<div><label for="id_subject">Subject:</label><input type="text" name="subject" maxlength="100" required id="id_subject">'
>>> f["subject"].label = "Topic"
>>> f.as_div().split("</div>")[0]
'<div><label for="id_subject">Topic:</label><input type="text" name="subject" maxlength="100" required id="id_subject">'
Не изменяйте атрибут base_fields, поскольку это изменение повлияет на все последующие экземпляры ContactForm в том же процессе Python:
>>> f.base_fields["subject"].label_suffix = "?"
>>> another_f = ContactForm(auto_id=False)
>>> another_f.as_div().split("</div>")[0]
'<div><label for="id_subject">Subject?</label><input type="text" name="subject" maxlength="100" required id="id_subject">'
Доступ к «очищенным» данным
-
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, а CharFields представляют пустые значения пустой строкой. Для каждого типа поля определено собственное «пустое» значение: например, для DateField это None, а не пустая строка. Полное описание поведения каждого поля в этом случае см. в примечании «Пустое значение» для каждого поля в разделе Встроенные классы полей ниже.
Можно написать код для проверки отдельных полей формы (по их именам) или формы целиком (с учётом сочетаний различных полей). Дополнительную информацию см. в разделе Проверка формы и полей.
Вывод форм в формате HTML
Вторая задача объекта Form — отображать себя в формате HTML. Для этого print он:
>>> f = ContactForm() >>> print(f) <div><label for="id_subject">Subject:</label><input type="text" name="subject" maxlength="100" required id="id_subject"></div> <div><label for="id_message">Message:</label><input type="text" name="message" required id="id_message"></div> <div><label for="id_sender">Sender:</label><input type="email" name="sender" required id="id_sender"></div> <div><label for="id_cc_myself">Cc myself:</label><input type="checkbox" name="cc_myself" id="id_cc_myself"></div>
Если форма связана с данными, вывод 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)
<div><label for="id_subject">Subject:</label><input type="text" name="subject" value="hello" maxlength="100" required id="id_subject"></div>
<div><label for="id_message">Message:</label><input type="text" name="message" value="Hi there" required id="id_message"></div>
<div><label for="id_sender">Sender:</label><input type="email" name="sender" value="foo@example.com" required id="id_sender"></div>
<div><label for="id_cc_myself">Cc myself:</label><input type="checkbox" name="cc_myself" id="id_cc_myself" checked></div>
Этот вывод по умолчанию заключает каждое поле в <div>. Обратите внимание на следующее:
- Для гибкости вывод не включает теги
<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'.
Хотя вывод <div> используется по умолчанию при вызове print формы, его можно настроить с помощью собственного шаблона формы, который можно задать для всего сайта, для отдельной формы или для отдельного экземпляра. См. раздел Повторно используемые шаблоны форм.
Отображение по умолчанию
При вызове print формы для её отображения по умолчанию используются следующие методы и атрибуты.
template_name
-
Form.template_name
Имя шаблона, отображаемого при преобразовании формы в строку, например с помощью print(form) или в шаблоне с помощью {{ form }}.
По умолчанию это свойство возвращает значение form_template_name средства отображения. Чтобы переопределить это значение для определённого класса формы, можно задать имя шаблона в виде строки.
render()
-
Form.render(template_name=None, context=None, renderer=None)
Метод render вызывается объектом __str__, а также методами Form.as_div(), Form.as_table(), Form.as_p() и Form.as_ul(). Все аргументы необязательны и по умолчанию имеют следующие значения:
-
template_name:Form.template_name -
context: значение, возвращаемое методомForm.get_context() -
renderer: значение, возвращаемое методомForm.default_renderer
Передав template_name, можно настроить шаблон, используемый только для одного вызова.
get_context()
-
Form.get_context()
Возвращает контекст шаблона для отображения формы.
Доступный контекст:
-
form: связанная форма. -
fields: все связанные поля, кроме скрытых. -
hidden_fields: все связанные скрытые поля. -
errors: все ошибки формы, не связанные с полем или связанные со скрытым полем.
template_name_label
-
Form.template_name_label
Шаблон, используемый для отображения <label> поля при вызове BoundField.label_tag()/legend_tag(). Его можно изменить для отдельной формы, переопределив этот атрибут, или более общим образом — переопределив шаблон по умолчанию. См. также раздел Переопределение встроенных шаблонов форм.
Стили вывода
Рекомендуемый способ изменить стиль вывода формы — задать собственный шаблон формы для всего сайта, отдельной формы или отдельного экземпляра. Примеры см. в разделе Повторно используемые шаблоны форм.
Для обратной совместимости предоставлены следующие вспомогательные функции. Они являются прокси для Form.render(), которому передаётся соответствующее значение template_name.
Примечание
Из шаблонов и стилей вывода, предоставляемых фреймворком, рекомендуется использовать вариант as_div() вместо вариантов as_p(), as_table() и as_ul(), поскольку шаблон реализует <fieldset> и <legend> для группировки связанных полей и упрощает навигацию для пользователей программ чтения с экрана.
Каждая вспомогательная функция связывает метод формы с атрибутом, задающим соответствующее имя шаблона.
as_div()
-
Form.template_name_div
Шаблон, используемый методом as_div(). По умолчанию: 'django/forms/div.html'.
-
Form.as_div()
Метод as_div() отображает форму в виде набора элементов <div>, каждый из которых <div> содержит одно поле, например:
>>> f = ContactForm() >>> f.as_div()
… выводит HTML следующего вида:
<div> <label for="id_subject">Subject:</label> <input type="text" name="subject" maxlength="100" required id="id_subject"> </div> <div> <label for="id_message">Message:</label> <input type="text" name="message" required id="id_message"> </div> <div> <label for="id_sender">Sender:</label> <input type="email" name="sender" required id="id_sender"> </div> <div> <label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself"> </div>
as_p()
-
Form.template_name_p
Шаблон, используемый методом as_p(). По умолчанию: 'django/forms/p.html'.
-
Form.as_p()
Метод as_p() отображает форму в виде набора тегов <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.template_name_ul
Шаблон, используемый методом as_ul(). По умолчанию: 'django/forms/ul.html'.
-
Form.as_ul()
Метод as_ul() отображает форму в виде набора тегов <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.template_name_table
Шаблон, используемый методом as_table(). По умолчанию: 'django/forms/table.html'.
-
Form.as_table()
Метод as_table() отображает форму в виде 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.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> <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)
<div class="required"><label for="id_subject" class="required">Subject:</label> ...
<div class="required"><label for="id_message" class="required">Message:</label> ...
<div class="required"><label for="id_sender" class="required">Sender:</label> ...
<div><label for="id_cc_myself">Cc myself:</label> ...
>>> f["subject"].label_tag()
<label class="required" for="id_subject">Subject:</label>
>>> f["subject"].legend_tag()
<legend class="required" for="id_subject">Subject:</legend>
>>> f["subject"].label_tag(attrs={"class": "foo"})
<label for="id_subject" class="foo required">Subject:</label>
>>> f["subject"].legend_tag(attrs={"class": "foo"})
<legend for="id_subject" class="foo required">Subject:</legend>
Дополнительно изменить отображение строк формы можно с помощью пользовательского BoundField.
Настройка отображения виджетов формы
-
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 и при создании экземпляра Form указан аргумент field_order, приоритет будет иметь последний 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,
... }
>>> ContactForm(data).as_div()
… выводит HTML следующего вида:
<div>
<label for="id_subject">Subject:</label>
<ul class="errorlist" id="id_subject_error"><li>This field is required.</li></ul>
<input type="text" name="subject" maxlength="100" required aria-invalid="true" aria-describedby="id_subject_error" id="id_subject">
</div>
<div>
<label for="id_message">Message:</label>
<textarea name="message" cols="40" rows="10" required id="id_message">Hi there</textarea>
</div>
<div>
<label for="id_sender">Sender:</label>
<ul class="errorlist" id="id_sender_error"><li>Enter a valid email address.</li></ul>
<input type="email" name="sender" value="invalid email address" maxlength="320" required aria-invalid="true" aria-describedby="id_sender_error" id="id_sender">
</div>
<div>
<label for="id_cc_myself">Cc myself:</label>
<input type="checkbox" name="cc_myself" id="id_cc_myself" checked>
</div>
Шаблоны форм Django по умолчанию связывают ошибки проверки с соответствующим полем ввода с помощью HTML-атрибута aria-describedby, если у поля есть auto_id и не задан пользовательский aria-describedby. Если при определении виджета задан пользовательский aria-describedby, он заменит значение по умолчанию.
Если виджет отображается внутри <fieldset>, атрибут aria-describedby добавляется к этому элементу, в противном случае он добавляется к HTML-элементу виджета (например, <input>).
Добавлен aria-describedby для связи ошибок с соответствующим полем ввода.
Настройка формата списка ошибок
-
class ErrorList(initlist=None, error_class=None, renderer=None, field_id=None)[исходный код] -
По умолчанию формы используют
django.forms.utils.ErrorListдля форматирования ошибок проверки.ErrorList— это объект, похожий на список, гдеinitlist— список ошибок. Кроме того, этот класс имеет следующие атрибуты и методы.Изменено в Django 5.2:Добавлен аргумент
field_id.-
error_class -
CSS-классы, используемые при отображении списка ошибок. Все указанные классы добавляются к классу
errorlist, используемому по умолчанию.
-
renderer -
Указывает средство отображения, используемое для
ErrorList. По умолчанию заданоNone, то есть используется средство отображения по умолчанию, указанное параметромFORM_RENDERER.
-
field_id -
Добавлено в Django 5.2.
Значение
idполя, к которому относятся ошибки. Это позволяет добавить HTML-атрибутidв шаблон ошибки и использовать его для связи ошибок с полем. В шаблоне по умолчанию используется форматid="{{ field_id }}_error", а значение передаётся методомForm.add_error()с помощью атрибута поляauto_id.
-
template_name -
Имя шаблона, используемого при вызове
__str__илиrender(). По умолчанию задано'django/forms/errors/list/default.html', которое служит прокси для шаблона'ul.html'.
-
template_name_text -
Имя шаблона, используемого при вызове
as_text(). По умолчанию задано'django/forms/errors/list/text.html'. Этот шаблон отображает ошибки в виде маркированного списка.
-
template_name_ul -
Имя шаблона, используемого при вызове
as_ul(). По умолчанию задано'django/forms/errors/list/ul.html'. Этот шаблон отображает ошибки в тегах<li>, обёрнутых в<ul>с CSS-классами, заданными атрибутомerror_class.
-
get_context()[исходный код] -
Возвращает контекст для отображения ошибок в шаблоне.
Доступный контекст:
-
errors: список ошибок. -
error_class: строка CSS-классов.
-
-
render(template_name=None, context=None, renderer=None) -
Метод 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или, в более общем случае, переопределить шаблон по умолчанию. См. также раздел Переопределение встроенных шаблонов форм. -
Более детализированный вывод
Методы as_p(), as_ul() и as_table() — это сокращенные варианты; они не единственный способ отображения объекта формы.
-
class BoundField[исходный код] -
Используется для отображения HTML или доступа к атрибутам отдельного поля экземпляра
Form.Метод
__str__()этого объекта отображает HTML-код для этого поля.Вы можете использовать
Form.bound_field_classиField.bound_field_class, чтобы задать разные классыBoundFieldдля формы или отдельного поля соответственно.Примеры переопределения
BoundFieldсм. в разделе Настройка BoundField.
Чтобы получить отдельный объект 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.aria_describedby[исходный код] -
Добавлено в Django 5.2.
Возвращает ссылку
aria-describedby, связывающую поле с текстом справки и ошибками. ВозвращаетNone, еслиaria-describedbyзадан вWidget.attrs, чтобы сохранить определенный пользователем атрибут при отображении формы.
-
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 aria-invalid="true"> >>> 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) ''При отображении поля с ошибками для его виджета устанавливается
aria-invalid="true", чтобы сообщить пользователям программ чтения с экрана о наличии ошибки.
-
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()/legend_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()/legend_tag().
-
BoundField.name -
Имя этого поля в форме:
>>> f = ContactForm() >>> print(f["subject"].name) subject >>> print(f["message"].name) message
-
BoundField.template_name[исходный код] -
Имя шаблона, отображаемого с помощью
BoundField.as_field_group().Свойство возвращает значение
template_name, если оно задано; в противном случае —field_template_name.
-
BoundField.use_fieldset[исходный код] -
Возвращает значение атрибута
use_fieldsetвиджета этого объекта BoundField.
-
BoundField.widget_type[исходный код] -
Возвращает имя класса виджета обернутого поля в нижнем регистре, удаляя конечные
inputилиwidget. Это свойство можно использовать при создании форм, в которых макет зависит от типа виджета. Например:{% for field in form %} {% if field.widget_type == 'checkbox' %} # render one way {% else %} # render another way {% endif %} {% endfor %}
Методы BoundField
-
BoundField.as_field_group() -
Отображает поле с помощью
BoundField.render()и значениями по умолчанию. При этом полеBoundFieldотображается вместе с меткой, текстом справки и ошибками с использованием шаблонаtemplate_name, если он задан; в противном случае используетсяfield_template_name.
-
Возвращает строку 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.get_context()[исходный код] -
Возвращает контекст шаблона для отображения поля. Доступный контекст — это
field, представляющий собой экземпляр связанного поля.
-
BoundField.label_tag(contents=None, attrs=None, label_suffix=None, tag=None)[исходный код] -
Отображает тег метки для поля формы с использованием шаблона, указанного в
Form.template_name_label.Доступный контекст:
-
field: этот экземплярBoundField. -
contents: по умолчанию — объединенная строка изBoundField.labelиForm.label_suffix(илиField.label_suffix, если задано). Это значение можно переопределить аргументамиcontentsиlabel_suffix. -
attrs:dict, содержащийfor,Form.required_css_classиid.idформируется виджетом поляattrsили свойствомBoundField.auto_id. Дополнительные атрибуты можно передать аргументомattrs. -
use_tag: логическое значение, равноеTrue, если у метки естьid. Если значениеFalse, шаблон по умолчанию опускаетtag. -
tag: необязательная строка для настройки тега; по умолчанию используется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или, в более общем случае, шаблон по умолчанию. См. также раздел Переопределение встроенных шаблонов форм. -
-
BoundField.legend_tag(contents=None, attrs=None, label_suffix=None)[исходный код] -
Вызывает
label_tag()сtag='legend', чтобы отобразить метку с тегами<legend>. Это полезно при отображении виджетов с переключателями и несколькими флажками, когда<legend>может быть уместнее, чем<label>.
-
BoundField.render(template_name=None, context=None, renderer=None) -
Метод render вызывается методом
as_field_group. Все аргументы необязательны; по умолчанию используются следующие значения:-
template_name:BoundField.template_name -
context: значение, возвращаемое методомBoundField.get_context() -
renderer: значение, возвращаемое методомForm.default_renderer
Передав
template_name, можно настроить шаблон для одного конкретного вызова. -
-
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
-
Form.bound_field_class
Определите пользовательский класс BoundField, который будет использоваться при отображении формы. Он имеет приоритет над BaseRenderer.bound_field_class на уровне проекта (вместе с пользовательским FORM_RENDERER), но может быть переопределен на уровне поля с помощью Field.bound_field_class.
Если bound_field_class не определен как переменная класса, его можно задать с помощью аргумента bound_field_class в конструкторе Form или Field.
Для обеспечения совместимости пользовательское поле формы по-прежнему может переопределять Field.get_bound_field() для использования пользовательского класса, однако предпочтительнее любой из описанных выше вариантов.
Пользовательский BoundField может понадобиться, если в шаблоне требуется получить дополнительные сведения о поле формы, а наследования от Field недостаточно.
Например, если у вас есть 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):
bound_field_class = GPSCoordinatesBoundField
Теперь в шаблоне можно получить доступ к стране с помощью {{ form.coordinates.country }}.
Также можно настроить отображение шаблона поля формы по умолчанию. Например, переопределите BoundField.label_tag(), чтобы добавить пользовательский класс:
class StyledLabelBoundField(BoundField):
def label_tag(self, contents=None, attrs=None, label_suffix=None, tag=None):
attrs = attrs or {}
attrs["class"] = "wide"
return super().label_tag(contents, attrs, label_suffix, tag)
class UserForm(forms.Form):
bound_field_class = StyledLabelBoundField
name = CharField()
Это изменит отображение формы по умолчанию:
>>> f = UserForm() >>> print(f["name"].label_tag) <label for="id_name" class="wide">Name:</label>
Чтобы добавить CSS-класс к оборачивающему HTML-элементу всех полей, можно переопределить BoundField, возвращающий другой набор CSS-классов:
class WrappedBoundField(BoundField):
def css_classes(self, extra_classes=None):
parent_css_classes = super().css_classes(extra_classes)
return f"field-class {parent_css_classes}".strip()
class UserForm(forms.Form):
bound_field_class = WrappedBoundField
name = CharField()
После этого форма будет отображаться следующим образом:
>>> f = UserForm() >>> print(f) <div class="field-class"><label for="id_name">Name:</label><input type="text" name="name" required id="id_name"></div>
Чтобы переопределить класс BoundField на уровне проекта, можно определить BaseRenderer.bound_field_class в пользовательском FORM_RENDERER:
mysite/renderers.pyfrom django.forms.renderers import DjangoTemplates
from .forms import CustomBoundField
class CustomRenderer(DjangoTemplates):
bound_field_class = CustomBoundField
settings.pyFORM_RENDERER = "mysite.renderers.CustomRenderer"
Привязка загруженных файлов к форме
Работа с формами, содержащими поля 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", b"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() сообщает, требуется ли форме кодирование 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) <div>Subject:<input type="text" name="subject" maxlength="100" required></div> <div>Message:<textarea name="message" cols="40" rows="10" required></textarea></div> <div>Sender:<input type="email" name="sender" required></div> <div>Cc myself:<input type="checkbox" name="cc_myself"></div> <div>Priority:<input type="text" name="priority" required></div>
Можно создать подкласс нескольких форм, используя их как примеси. В этом примере 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) <div>First name:<input type="text" name="first_name" required></div> <div>Last name:<input type="text" name="last_name" required></div> <div>Instrument:<input type="text" name="instrument" required></div> <div>Haircut type:<input type="text" name="haircut_type" required></div>
Унаследованное от родительского класса поле 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. Чтобы задать каждой Form собственное пространство имен, используйте именованный аргумент prefix:
>>> mother = PersonForm(prefix="mother") >>> father = PersonForm(prefix="father") >>> print(mother) <div><label for="id_mother-first_name">First name:</label><input type="text" name="mother-first_name" required id="id_mother-first_name"></div> <div><label for="id_mother-last_name">Last name:</label><input type="text" name="mother-last_name" required id="id_mother-last_name"></div> >>> print(father) <div><label for="id_father-first_name">First name:</label><input type="text" name="father-first_name" required id="id_father-first_name"></div> <div><label for="id_father-last_name">Last name:</label><input type="text" name="father-last_name" required id="id_father-last_name"></div>
Префикс также можно указать в классе формы:
>>> class PersonForm(forms.Form): ... ... ... prefix = "person" ...
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/6.0/ref/forms/api/