Spec-Zone.ru › Django 5.1

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 не является корректным email-адресом:

>>> 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 в представление формы, где клиент интерпретирует ответ и вставляет ошибки на страницу, вы должны убедиться, что экранируете результаты на стороне клиента, чтобы избежать возможности XSS-атаки. Вы можете сделать это в JavaScript с помощью element.textContent = errorText или с помощью jQuery's $(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)
<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 = CommentForm(auto_id=False)
>>> 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, а поля CharField обрабатывают пустые значения как пустые строки. Каждый тип поля знает, какое значение у него «пустое» – например, для DateField это None, а не пустая строка. Более подробную информацию о поведении каждого поля в этом случае см. в примечании «Пустое значение» для каждого поля в разделе «Встроенные Field классы» ниже.

Вы можете написать код для выполнения валидации конкретных полей формы (на основе их имени) или для всей формы (рассматривая сочетания различных полей). Более подробная информация об этом содержится в Валидация форм и полей.

Вывод форм в 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, а не стиль XHTML checked='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>.

Стилевание требуемых или ошибочных строк формы

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>

Настройка атрибутов 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)
<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>

Если auto_id установлено в True, тогда вывод формы будет включать теги <label> и будет использовать имя поля в качестве id для каждого поля формы:

>>> f = ContactForm(auto_id=True)
>>> print(f)
<div><label for="subject">Subject:</label><input type="text" name="subject" maxlength="100" required id="subject"></div>
<div><label for="message">Message:</label><textarea name="message" cols="40" rows="10" required id="message"></textarea></div>
<div><label for="sender">Sender:</label><input type="email" name="sender" required id="sender"></div>
<div><label for="cc_myself">Cc myself:</label><input type="checkbox" name="cc_myself" id="cc_myself"></div>

Если auto_id установлено на строку, содержащую символ формата '%s', тогда вывод формы будет включать теги <label>, и будет генерировать атрибуты id на основе строки формата. Например, для строки формата 'field_%s', поле с именем subject получит значение id 'field_subject'. Продолжая наш пример:

>>> f = ContactForm(auto_id="id_for_%s")
>>> print(f)
<div><label for="id_for_subject">Subject:</label><input type="text" name="subject" maxlength="100" required id="id_for_subject"></div>
<div><label for="id_for_message">Message:</label><textarea name="message" cols="40" rows="10" required id="id_for_message"></textarea></div>
<div><label for="id_for_sender">Sender:</label><input type="email" name="sender" required id="id_for_sender"></div>
<div><label for="id_for_cc_myself">Cc myself:</label><input type="checkbox" name="cc_myself" id="id_for_cc_myself"></div>

Если 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)
<div><label for="id_for_subject">Subject</label><input type="text" name="subject" maxlength="100" required id="id_for_subject"></div>
<div><label for="id_for_message">Message</label><textarea name="message" cols="40" rows="10" required id="id_for_message"></textarea></div>
<div><label for="id_for_sender">Sender</label><input type="email" name="sender" required id="id_for_sender"></div>
<div><label for="id_for_cc_myself">Cc myself</label><input type="checkbox" name="cc_myself" id="id_for_cc_myself"></div>
>>> f = ContactForm(auto_id="id_for_%s", label_suffix=" ->")
>>> print(f)
<div><label for="id_for_subject">Subject -&gt;</label><input type="text" name="subject" maxlength="100" required id="id_for_subject"></div>
<div><label for="id_for_message">Message -&gt;</label><textarea name="message" cols="40" rows="10" required id="id_for_message"></textarea></div>
<div><label for="id_for_sender">Sender -&gt;</label><input type="email" name="sender" required id="id_for_sender"></div>
<div><label for="id_for_cc_myself">Cc myself -&gt;</label><input type="checkbox" name="cc_myself" id="id_for_cc_myself"></div>

Обратите внимание, что суффикс метки добавляется только если последний символ метки не является знаком препинания (на английском языке это ., !, ? или :).

Поля также могут определять свой собственный label_suffix. Это будет иметь приоритет над Form.label_suffix. Суффикс также может быть переопределён во время выполнения с помощью параметра label_suffix для label_tag()/ legend_tag().

END_OF_DOCUMENT_MARKER
Form.use_required_attribute

Если установлено в True (по умолчанию), обязательные поля формы будут иметь атрибут required HTML.

Формы наборов экземплярируют формы с 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)
<div>Subject:
  <ul class="errorlist"><li>This field is required.</li></ul>
  <input type="text" name="subject" maxlength="100" required aria-invalid="true">
</div>
<div>Message:
  <textarea name="message" cols="40" rows="10" required>Hi there</textarea>
</div>
<div>Sender:
  <ul class="errorlist"><li>Enter a valid email address.</li></ul>
  <input type="email" name="sender" value="invalid email address" required aria-invalid="true">
</div>
<div>Cc myself:
  <input type="checkbox" name="cc_myself" checked>
</div>

Настройка формата списка ошибок

class ErrorList(initlist=None, error_class=None, renderer=None) [source]

По умолчанию формы используют django.forms.utils.ErrorList для форматирования ошибок валидации. ErrorList — это объект списка, где initlist является списком ошибок. Кроме того, у этого класса есть следующие атрибуты и методы.

error_class

Классы CSS, которые будут использоваться при рендеринге списка ошибок. Любые предоставленные классы добавляются к классу по умолчанию errorlist.

renderer

Указывает рендер, который следует использовать для ErrorList. По умолчанию None, что означает использование рендера по умолчанию, определенного настройкой FORM_RENDERER.

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() [source]

Возвращает контекст для отображения ошибок в шаблоне.

Доступный контекст:

  • 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 [source]

Используется для отображения 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 [source]

Атрибут HTML ID для данного BoundField. Возвращает пустую строку, если Form.auto_id имеет значение False.

BoundField.data [source]

Это свойство возвращает данные для этого 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 [source]

Объект, похожий на список, который отображается как 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" будет установлено в виджете поля для обозначения наличия ошибки для пользователей считывающих устройства.

Изменено в Django 5.0:

Добавлен 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 [source]

Используйте это свойство для рендеринга 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 [source]

Используйте 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().

BoundField.is_hidden [source]

Возвращает 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 [source]
Новое в Django 5.0.

Имя шаблона, используемого при рендеринге с BoundField.as_field_group().

Свойство, возвращающее значение template_name, если оно установлено, в противном случае field_template_name.

BoundField.use_fieldset [source]

Возвращает значение атрибута use_fieldset виджета этого BoundField.

BoundField.widget_type [source]

Возвращает имя класса обернутого виджета поля в нижнем регистре, с удалением любых последующих 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()
Новое в Django 5.0.

Рендерит поле используя BoundField.render() с настройками по умолчанию, которые рендерят BoundField, включая его метку, текст справки и ошибки, используя шаблон template_name если он установлен, в противном случае field_template_name

BoundField.as_hidden(attrs=None, **kwargs) [source]

Возвращает строку HTML для представления этого поля как <input type="hidden">.

**kwargs передаются в as_widget().

Этот метод в основном используется внутри. Вы должны использовать виджет вместо него.

BoundField.as_widget(widget=None, attrs=None, only_initial=False) [source]

Рендерит поле путём рендеринга переданного виджета, добавления любых атрибутов HTML, переданных как attrs. Если виджет не указан, используется виджет по умолчанию.

only_initial используется внутренними частями Django и не должно устанавливаться явно.

BoundField.css_classes(extra_classes=None) [source]

При использовании удобных методов рендеринга 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() [source]
Новое в Django 5.0.

Возвращает контекст шаблона для рендеринга поля. Доступный контекст — field — экземпляр связанного поля.

BoundField.label_tag(contents=None, attrs=None, label_suffix=None, tag=None) [source]

Рендерит тег метки для поля формы, используя шаблон, указанный в Form.template_name_label.

Доступный контекст:

  • field: Этот экземпляр BoundField.
  • contents: По умолчанию, конкатенированная строка из BoundField.label и Form.label_suffix (или Field.label_suffix, если задано). Это можно переопределить параметрами contents и label_suffix.
  • attrs: Словарь, содержащий 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) [source]

Вызывает label_tag() с tag='legend' для рендеринга метки с тегами <legend>. Это полезно при рендеринге виджетов радио и множественных чекбоксов, где <legend> может быть более подходящим, чем тег <label>.

BoundField.render(template_name=None, context=None, renderer=None)
Новое в Django 5.0.

Метод render вызывается as_field_group. Все аргументы являются необязательными и по умолчанию имеют значения:

  • template_name: BoundField.template_name
  • context: Значение, возвращённое BoundField.get_context()
  • renderer: Значение, возвращённое Form.default_renderer

Передав template_name, вы можете настроить шаблон, используемый только для одного вызова.

BoundField.value() [source]

Используйте этот метод для рендеринга исходного значения этого поля так, как оно отображалось бы в 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) [source]

Принимает экземпляр 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", 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()

Проверка на 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)
<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

Вы можете разместить несколько форм Django внутри одного тега <form>. Чтобы присвоить каждому 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/5.1/ref/forms/api/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API