1
0
mirror of https://github.com/django/django.git synced 2025-06-03 10:39:12 +00:00

Refs #32339 -- Updated docs to reflect default <div> style form rendering in Django 5.0.

Follow up to 98756c685ee173bbd43f21ed0553f808be835ce5.
This commit is contained in:
David Smith 2023-02-12 13:20:05 +00:00 committed by Mariusz Felisiak
parent 4038a8df0b
commit 232b60a21b
5 changed files with 102 additions and 131 deletions

View File

@ -276,9 +276,9 @@ precedence:
... comment = forms.CharField() ... comment = forms.CharField()
>>> f = CommentForm(initial={'name': 'instance'}, auto_id=False) >>> f = CommentForm(initial={'name': 'instance'}, auto_id=False)
>>> print(f) >>> print(f)
<tr><th>Name:</th><td><input type="text" name="name" value="instance" required></td></tr> <div>Name:<input type="text" name="name" value="instance" required></div>
<tr><th>Url:</th><td><input type="url" name="url" required></td></tr> <div>Url:<input type="url" name="url" required></div>
<tr><th>Comment:</th><td><input type="text" name="comment" required></td></tr> <div>Comment:<input type="text" name="comment" required></div>
.. method:: Form.get_initial_for_field(field, field_name) .. method:: Form.get_initial_for_field(field, field_name)
@ -500,10 +500,10 @@ The second task of a ``Form`` object is to render itself as HTML. To do so,
>>> f = ContactForm() >>> f = ContactForm()
>>> print(f) >>> print(f)
<tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" required></td></tr> <div><label for="id_subject">Subject:</label><input type="text" name="subject" maxlength="100" required id="id_subject"></div>
<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" required></td></tr> <div><label for="id_message">Message:</label><input type="text" name="message" required id="id_message"></div>
<tr><th><label for="id_sender">Sender:</label></th><td><input type="email" name="sender" id="id_sender" required></td></tr> <div><label for="id_sender">Sender:</label><input type="email" name="sender" required id="id_sender"></div>
<tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself"></td></tr> <div><label for="id_cc_myself">Cc myself:</label><input type="checkbox" name="cc_myself" id="id_cc_myself"></div>
If the form is bound to data, the HTML output will include that data If the form is bound to data, the HTML output will include that data
appropriately. For example, if a field is represented by an appropriately. For example, if a field is represented by an
@ -519,16 +519,14 @@ include ``checked`` if appropriate:
... 'cc_myself': True} ... 'cc_myself': True}
>>> f = ContactForm(data) >>> f = ContactForm(data)
>>> print(f) >>> print(f)
<tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" value="hello" required></td></tr> <div><label for="id_subject">Subject:</label><input type="text" name="subject" value="hello" maxlength="100" required id="id_subject"></div>
<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" value="Hi there" required></td></tr> <div><label for="id_message">Message:</label><input type="text" name="message" value="Hi there" required id="id_message"></div>
<tr><th><label for="id_sender">Sender:</label></th><td><input type="email" name="sender" id="id_sender" value="foo@example.com" required></td></tr> <div><label for="id_sender">Sender:</label><input type="email" name="sender" value="foo@example.com" required id="id_sender"></div>
<tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" checked></td></tr> <div><label for="id_cc_myself">Cc myself:</label><input type="checkbox" name="cc_myself" id="id_cc_myself" checked></div>
This default output is a two-column HTML table, with a ``<tr>`` for each field. This default output wraps each field with a ``<div>``. Notice the following:
Notice the following:
* For flexibility, the output does *not* include the ``<table>`` and * For flexibility, the output does *not* include the ``<form>`` and ``</form>``
``</table>`` tags, nor does it include the ``<form>`` and ``</form>``
tags or an ``<input type="submit">`` tag. It's your job to do that. tags or an ``<input type="submit">`` tag. It's your job to do that.
* Each field type has a default HTML representation. ``CharField`` is * Each field type has a default HTML representation. ``CharField`` is
@ -556,7 +554,7 @@ Notice the following:
it uses boolean attributes such as ``checked`` rather than the XHTML style it uses boolean attributes such as ``checked`` rather than the XHTML style
of ``checked='checked'``. of ``checked='checked'``.
Although ``<table>`` output is the default output style when you ``print`` a Although ``<div>`` output is the default output style when you ``print`` a
form, other output styles are available. Each style is available as a method on form, other output styles are available. Each style is available as a method on
a form object, and each rendering method returns a string. a form object, and each rendering method returns a string.
@ -584,7 +582,7 @@ class.
.. method:: Form.render(template_name=None, context=None, renderer=None) .. method:: Form.render(template_name=None, context=None, renderer=None)
The render method is called by ``__str__`` as well as the The render method is called by ``__str__`` as well as the :meth:`.Form.as_div`,
:meth:`.Form.as_table`, :meth:`.Form.as_p`, and :meth:`.Form.as_ul` methods. :meth:`.Form.as_table`, :meth:`.Form.as_p`, and :meth:`.Form.as_ul` methods.
All arguments are optional and default to: All arguments are optional and default to:
@ -779,11 +777,11 @@ classes, as needed. The HTML will look something like:
.. code-block:: pycon .. code-block:: pycon
>>> f = ContactForm(data) >>> f = ContactForm(data)
>>> print(f.as_table()) >>> print(f)
<tr class="required"><th><label class="required" for="id_subject">Subject:</label> ... <div class="required"><label for="id_subject" class="required">Subject:</label> ...
<tr class="required"><th><label class="required" for="id_message">Message:</label> ... <div class="required"><label for="id_message" class="required">Message:</label> ...
<tr class="required error"><th><label class="required" for="id_sender">Sender:</label> ... <div class="required"><label for="id_sender" class="required">Sender:</label> ...
<tr><th><label for="id_cc_myself">Cc myself:<label> ... <div><label for="id_cc_myself">Cc myself:</label> ...
>>> f['subject'].label_tag() >>> f['subject'].label_tag()
<label class="required" for="id_subject">Subject:</label> <label class="required" for="id_subject">Subject:</label>
>>> f['subject'].legend_tag() >>> f['subject'].legend_tag()
@ -823,7 +821,7 @@ tags nor ``id`` attributes:
.. code-block:: pycon .. code-block:: pycon
>>> f = ContactForm(auto_id=False) >>> f = ContactForm(auto_id=False)
>>> print(f.as_div()) >>> print(f)
<div>Subject:<input type="text" name="subject" maxlength="100" required></div> <div>Subject:<input type="text" name="subject" maxlength="100" required></div>
<div>Message:<textarea name="message" cols="40" rows="10" required></textarea></div> <div>Message:<textarea name="message" cols="40" rows="10" required></textarea></div>
<div>Sender:<input type="email" name="sender" required></div> <div>Sender:<input type="email" name="sender" required></div>
@ -836,7 +834,7 @@ field:
.. code-block:: pycon .. code-block:: pycon
>>> f = ContactForm(auto_id=True) >>> f = ContactForm(auto_id=True)
>>> print(f.as_div()) >>> print(f)
<div><label for="subject">Subject:</label><input type="text" name="subject" maxlength="100" required id="subject"></div> <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="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="sender">Sender:</label><input type="email" name="sender" required id="sender"></div>
@ -851,7 +849,7 @@ attributes based on the format string. For example, for a format string
.. code-block:: pycon .. code-block:: pycon
>>> f = ContactForm(auto_id='id_for_%s') >>> f = ContactForm(auto_id='id_for_%s')
>>> print(f.as_div()) >>> 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_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_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_sender">Sender:</label><input type="email" name="sender" required id="id_for_sender"></div>
@ -873,13 +871,13 @@ It's possible to customize that character, or omit it entirely, using the
.. code-block:: pycon .. code-block:: pycon
>>> f = ContactForm(auto_id='id_for_%s', label_suffix='') >>> f = ContactForm(auto_id='id_for_%s', label_suffix='')
>>> print(f.as_div()) >>> 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_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_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_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> <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=' ->') >>> f = ContactForm(auto_id='id_for_%s', label_suffix=' ->')
>>> print(f.as_div()) >>> 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_subject">Subject:</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_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_sender">Sender -&gt;</label><input type="email" name="sender" required id="id_for_sender"></div>
@ -972,28 +970,11 @@ method you're using:
... 'sender': 'invalid email address', ... 'sender': 'invalid email address',
... 'cc_myself': True} ... 'cc_myself': True}
>>> f = ContactForm(data, auto_id=False) >>> f = ContactForm(data, auto_id=False)
>>> print(f.as_div()) >>> print(f)
<div>Subject:<ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="subject" maxlength="100" required></div> <div>Subject:<ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="subject" maxlength="100" required></div>
<div>Message:<textarea name="message" cols="40" rows="10" required>Hi there</textarea></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></div> <div>Sender:<ul class="errorlist"><li>Enter a valid email address.</li></ul><input type="email" name="sender" value="invalid email address" required></div>
<div>Cc myself:<input type="checkbox" name="cc_myself" checked></div> <div>Cc myself:<input type="checkbox" name="cc_myself" checked></div>
>>> print(f.as_table())
<tr><th>Subject:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="subject" maxlength="100" required></td></tr>
<tr><th>Message:</th><td><textarea name="message" cols="40" rows="10" required></textarea></td></tr>
<tr><th>Sender:</th><td><ul class="errorlist"><li>Enter a valid email address.</li></ul><input type="email" name="sender" value="invalid email address" required></td></tr>
<tr><th>Cc myself:</th><td><input checked type="checkbox" name="cc_myself"></td></tr>
>>> print(f.as_ul())
<li><ul class="errorlist"><li>This field is required.</li></ul>Subject: <input type="text" name="subject" maxlength="100" required></li>
<li>Message: <textarea name="message" cols="40" rows="10" required></textarea></li>
<li><ul class="errorlist"><li>Enter a valid email address.</li></ul>Sender: <input type="email" name="sender" value="invalid email address" required></li>
<li>Cc myself: <input checked type="checkbox" name="cc_myself"></li>
>>> print(f.as_p())
<p><ul class="errorlist"><li>This field is required.</li></ul></p>
<p>Subject: <input type="text" name="subject" maxlength="100" required></p>
<p>Message: <textarea name="message" cols="40" rows="10" required></textarea></p>
<p><ul class="errorlist"><li>Enter a valid email address.</li></ul></p>
<p>Sender: <input type="email" name="sender" value="invalid email address" required></p>
<p>Cc myself: <input checked type="checkbox" name="cc_myself"></p>
.. _ref-forms-error-list-format: .. _ref-forms-error-list-format:
@ -1515,7 +1496,7 @@ fields are ordered first:
>>> class ContactFormWithPriority(ContactForm): >>> class ContactFormWithPriority(ContactForm):
... priority = forms.CharField() ... priority = forms.CharField()
>>> f = ContactFormWithPriority(auto_id=False) >>> f = ContactFormWithPriority(auto_id=False)
>>> print(f.as_div()) >>> print(f)
<div>Subject:<input type="text" name="subject" maxlength="100" required></div> <div>Subject:<input type="text" name="subject" maxlength="100" required></div>
<div>Message:<textarea name="message" cols="40" rows="10" required></textarea></div> <div>Message:<textarea name="message" cols="40" rows="10" required></textarea></div>
<div>Sender:<input type="email" name="sender" required></div> <div>Sender:<input type="email" name="sender" required></div>
@ -1538,7 +1519,7 @@ classes:
>>> class BeatleForm(InstrumentForm, PersonForm): >>> class BeatleForm(InstrumentForm, PersonForm):
... haircut_type = forms.CharField() ... haircut_type = forms.CharField()
>>> b = BeatleForm(auto_id=False) >>> b = BeatleForm(auto_id=False)
>>> print(b.as_div()) >>> print(b)
<div>First name:<input type="text" name="first_name" required></div> <div>First name:<input type="text" name="first_name" required></div>
<div>Last name:<input type="text" name="last_name" required></div> <div>Last name:<input type="text" name="last_name" required></div>
<div>Instrument:<input type="text" name="instrument" required></div> <div>Instrument:<input type="text" name="instrument" required></div>
@ -1575,10 +1556,10 @@ You can put several Django forms inside one ``<form>`` tag. To give each
>>> mother = PersonForm(prefix="mother") >>> mother = PersonForm(prefix="mother")
>>> father = PersonForm(prefix="father") >>> father = PersonForm(prefix="father")
>>> print(mother.as_div()) >>> 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-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> <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.as_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-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> <div><label for="id_father-last_name">Last name:</label><input type="text" name="father-last_name" required id="id_father-last_name"></div>

View File

@ -129,9 +129,9 @@ We've specified ``auto_id=False`` to simplify the output:
... comment = forms.CharField() ... comment = forms.CharField()
>>> f = CommentForm(auto_id=False) >>> f = CommentForm(auto_id=False)
>>> print(f) >>> print(f)
<tr><th>Your name:</th><td><input type="text" name="name" required></td></tr> <div>Your name:<input type="text" name="name" required></div>
<tr><th>Your website:</th><td><input type="url" name="url"></td></tr> <div>Your website:<input type="url" name="url"></div>
<tr><th>Comment:</th><td><input type="text" name="comment" required></td></tr> <div>Comment:<input type="text" name="comment" required></div>
``label_suffix`` ``label_suffix``
---------------- ----------------
@ -148,10 +148,10 @@ The ``label_suffix`` argument lets you override the form's
... nationality = forms.CharField() ... nationality = forms.CharField()
... captcha_answer = forms.IntegerField(label='2 + 2', label_suffix=' =') ... captcha_answer = forms.IntegerField(label='2 + 2', label_suffix=' =')
>>> f = ContactForm(label_suffix='?') >>> f = ContactForm(label_suffix='?')
>>> print(f.as_p()) >>> print(f)
<p><label for="id_age">Age?</label> <input id="id_age" name="age" type="number" required></p> <div><label for="id_age">Age?</label><input type="number" name="age" required id="id_age"></div>
<p><label for="id_nationality">Nationality?</label> <input id="id_nationality" name="nationality" type="text" required></p> <div><label for="id_nationality">Nationality?</label><input type="text" name="nationality" required id="id_nationality"></div>
<p><label for="id_captcha_answer">2 + 2 =</label> <input id="id_captcha_answer" name="captcha_answer" type="number" required></p> <div><label for="id_captcha_answer">2 + 2 =</label><input type="number" name="captcha_answer" required id="id_captcha_answer"></div>
``initial`` ``initial``
----------- -----------
@ -175,9 +175,9 @@ field is initialized to a particular value. For example:
... comment = forms.CharField() ... comment = forms.CharField()
>>> f = CommentForm(auto_id=False) >>> f = CommentForm(auto_id=False)
>>> print(f) >>> print(f)
<tr><th>Name:</th><td><input type="text" name="name" value="Your name" required></td></tr> <div>Name:<input type="text" name="name" value="Your name" required></div>
<tr><th>Url:</th><td><input type="url" name="url" value="http://" required></td></tr> <div>Url:<input type="url" name="url" value="http://" required></div>
<tr><th>Comment:</th><td><input type="text" name="comment" required></td></tr> <div>Comment:<input type="text" name="comment" required></div>
You may be thinking, why not just pass a dictionary of the initial values as You may be thinking, why not just pass a dictionary of the initial values as
data when displaying the form? Well, if you do that, you'll trigger validation, data when displaying the form? Well, if you do that, you'll trigger validation,
@ -192,9 +192,9 @@ and the HTML output will include any validation errors:
>>> default_data = {'name': 'Your name', 'url': 'http://'} >>> default_data = {'name': 'Your name', 'url': 'http://'}
>>> f = CommentForm(default_data, auto_id=False) >>> f = CommentForm(default_data, auto_id=False)
>>> print(f) >>> print(f)
<tr><th>Name:</th><td><input type="text" name="name" value="Your name" required></td></tr> <div>Name:<input type="text" name="name" value="Your name" required></div>
<tr><th>Url:</th><td><ul class="errorlist"><li>Enter a valid URL.</li></ul><input type="url" name="url" value="http://" required></td></tr> <div>Url:<ul class="errorlist"><li>Enter a valid URL.</li></ul><input type="url" name="url" value="http://" required></div>
<tr><th>Comment:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="comment" required></td></tr> <div>Comment:<ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="comment" required></div>
This is why ``initial`` values are only displayed for unbound forms. For bound This is why ``initial`` values are only displayed for unbound forms. For bound
forms, the HTML output will use the bound data. forms, the HTML output will use the bound data.
@ -225,7 +225,7 @@ Instead of a constant, you can also pass any callable:
>>> class DateForm(forms.Form): >>> class DateForm(forms.Form):
... day = forms.DateField(initial=datetime.date.today) ... day = forms.DateField(initial=datetime.date.today)
>>> print(DateForm()) >>> print(DateForm())
<tr><th>Day:</th><td><input type="text" name="day" value="12/23/2008" required><td></tr> <div><label for="id_day">Day:</label><input type="text" name="day" value="2023-02-11" required id="id_day"></div>
The callable will be evaluated only when the unbound form is displayed, not when it is defined. The callable will be evaluated only when the unbound form is displayed, not when it is defined.
@ -262,21 +262,11 @@ fields. We've specified ``auto_id=False`` to simplify the output:
... sender = forms.EmailField(help_text='A valid email address, please.') ... sender = forms.EmailField(help_text='A valid email address, please.')
... cc_myself = forms.BooleanField(required=False) ... cc_myself = forms.BooleanField(required=False)
>>> f = HelpTextContactForm(auto_id=False) >>> f = HelpTextContactForm(auto_id=False)
>>> print(f.as_table()) >>> print(f)
<tr><th>Subject:</th><td><input type="text" name="subject" maxlength="100" required><br><span class="helptext">100 characters max.</span></td></tr> <div>Subject:<div class="helptext">100 characters max.</div><input type="text" name="subject" maxlength="100" required></div>
<tr><th>Message:</th><td><input type="text" name="message" required></td></tr> <div>Message:<input type="text" name="message" required></div>
<tr><th>Sender:</th><td><input type="email" name="sender" required><br>A valid email address, please.</td></tr> <div>Sender:<div class="helptext">A valid email address, please.</div><input type="email" name="sender" required></div>
<tr><th>Cc myself:</th><td><input type="checkbox" name="cc_myself"></td></tr> <div>Cc myself:<input type="checkbox" name="cc_myself"></div>
>>> print(f.as_ul()))
<li>Subject: <input type="text" name="subject" maxlength="100" required> <span class="helptext">100 characters max.</span></li>
<li>Message: <input type="text" name="message" required></li>
<li>Sender: <input type="email" name="sender" required> A valid email address, please.</li>
<li>Cc myself: <input type="checkbox" name="cc_myself"></li>
>>> print(f.as_p())
<p>Subject: <input type="text" name="subject" maxlength="100" required> <span class="helptext">100 characters max.</span></p>
<p>Message: <input type="text" name="message" required></p>
<p>Sender: <input type="email" name="sender" required> A valid email address, please.</p>
<p>Cc myself: <input type="checkbox" name="cc_myself"></p>
``error_messages`` ``error_messages``
------------------ ------------------

View File

@ -144,10 +144,10 @@ provided for each widget will be rendered exactly the same:
.. code-block:: pycon .. code-block:: pycon
>>> f = CommentForm(auto_id=False) >>> f = CommentForm(auto_id=False)
>>> f.as_table() >>> print(f)
<tr><th>Name:</th><td><input type="text" name="name" required></td></tr> <div>Name:<input type="text" name="name" required></div>
<tr><th>Url:</th><td><input type="url" name="url" required></td></tr> <div>Url:<input type="url" name="url" required></div>
<tr><th>Comment:</th><td><input type="text" name="comment" required></td></tr> <div>Comment:<input type="text" name="comment" required></div>
On a real web page, you probably don't want every widget to look the same. You On a real web page, you probably don't want every widget to look the same. You
might want a larger input element for the comment, and you might want the might want a larger input element for the comment, and you might want the
@ -182,10 +182,10 @@ you can use the :attr:`Form.fields` attribute::
Django will then include the extra attributes in the rendered output: Django will then include the extra attributes in the rendered output:
>>> f = CommentForm(auto_id=False) >>> f = CommentForm(auto_id=False)
>>> f.as_table() >>> print(f)
<tr><th>Name:</th><td><input type="text" name="name" class="special" required></td></tr> <div>Name:<input type="text" name="name" class="special" required></div>
<tr><th>Url:</th><td><input type="url" name="url" required></td></tr> <div>Url:<input type="url" name="url" required></div>
<tr><th>Comment:</th><td><input type="text" name="comment" size="40" required></td></tr> <div>Comment:<input type="text" name="comment" size="40" required></div>
You can also set the HTML ``id`` using :attr:`~Widget.attrs`. See You can also set the HTML ``id`` using :attr:`~Widget.attrs`. See
:attr:`BoundField.id_for_label` for an example. :attr:`BoundField.id_for_label` for an example.

View File

@ -33,9 +33,9 @@ in the formset and display them as you would with a regular form:
>>> formset = ArticleFormSet() >>> formset = ArticleFormSet()
>>> for form in formset: >>> for form in formset:
... print(form.as_table()) ... print(form)
<tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" id="id_form-0-title"></td></tr> <div><label for="id_form-0-title">Title:</label><input type="text" name="form-0-title" id="id_form-0-title"></div>
<tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" id="id_form-0-pub_date"></td></tr> <div><label for="id_form-0-pub_date">Pub date:</label><input type="text" name="form-0-pub_date" id="id_form-0-pub_date"></div>
As you can see it only displayed one empty form. The number of empty forms As you can see it only displayed one empty form. The number of empty forms
that is displayed is controlled by the ``extra`` parameter. By default, that is displayed is controlled by the ``extra`` parameter. By default,
@ -77,13 +77,13 @@ example:
... ]) ... ])
>>> for form in formset: >>> for form in formset:
... print(form.as_table()) ... print(form)
<tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" value="Django is now open source" id="id_form-0-title"></td></tr> <div><label for="id_form-0-title">Title:</label><input type="text" name="form-0-title" value="Django is now open source" id="id_form-0-title"></div>
<tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" value="2008-05-12" id="id_form-0-pub_date"></td></tr> <div><label for="id_form-0-pub_date">Pub date:</label><input type="text" name="form-0-pub_date" value="2023-02-11" id="id_form-0-pub_date"></div>
<tr><th><label for="id_form-1-title">Title:</label></th><td><input type="text" name="form-1-title" id="id_form-1-title"></td></tr> <div><label for="id_form-1-title">Title:</label><input type="text" name="form-1-title" id="id_form-1-title"></div>
<tr><th><label for="id_form-1-pub_date">Pub date:</label></th><td><input type="text" name="form-1-pub_date" id="id_form-1-pub_date"></td></tr> <div><label for="id_form-1-pub_date">Pub date:</label><input type="text" name="form-1-pub_date" id="id_form-1-pub_date"></div>
<tr><th><label for="id_form-2-title">Title:</label></th><td><input type="text" name="form-2-title" id="id_form-2-title"></td></tr> <div><label for="id_form-2-title">Title:</label><input type="text" name="form-2-title" id="id_form-2-title"></div>
<tr><th><label for="id_form-2-pub_date">Pub date:</label></th><td><input type="text" name="form-2-pub_date" id="id_form-2-pub_date"></td></tr> <div><label for="id_form-2-pub_date">Pub date:</label><input type="text" name="form-2-pub_date" id="id_form-2-pub_date"></div>
There are now a total of three forms showing above. One for the initial data There are now a total of three forms showing above. One for the initial data
that was passed in and two extra forms. Also note that we are passing in a that was passed in and two extra forms. Also note that we are passing in a
@ -113,9 +113,9 @@ gives you the ability to limit the number of forms the formset will display:
>>> ArticleFormSet = formset_factory(ArticleForm, extra=2, max_num=1) >>> ArticleFormSet = formset_factory(ArticleForm, extra=2, max_num=1)
>>> formset = ArticleFormSet() >>> formset = ArticleFormSet()
>>> for form in formset: >>> for form in formset:
... print(form.as_table()) ... print(form)
<tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" id="id_form-0-title"></td></tr> <div><label for="id_form-0-title">Title:</label><input type="text" name="form-0-title" id="id_form-0-title"></div>
<tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" id="id_form-0-pub_date"></td></tr> <div><label for="id_form-0-pub_date">Pub date:</label><input type="text" name="form-0-pub_date" id="id_form-0-pub_date"></div>
If the value of ``max_num`` is greater than the number of existing items in the If the value of ``max_num`` is greater than the number of existing items in the
initial data, up to ``extra`` additional blank forms will be added to the initial data, up to ``extra`` additional blank forms will be added to the
@ -517,16 +517,16 @@ Lets you create a formset with the ability to order:
... {'title': 'Article #2', 'pub_date': datetime.date(2008, 5, 11)}, ... {'title': 'Article #2', 'pub_date': datetime.date(2008, 5, 11)},
... ]) ... ])
>>> for form in formset: >>> for form in formset:
... print(form.as_table()) ... print(form)
<tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" value="Article #1" id="id_form-0-title"></td></tr> <div><label for="id_form-0-title">Title:</label><input type="text" name="form-0-title" value="Article #1" id="id_form-0-title"></div>
<tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" value="2008-05-10" id="id_form-0-pub_date"></td></tr> <div><label for="id_form-0-pub_date">Pub date:</label><input type="text" name="form-0-pub_date" value="2008-05-10" id="id_form-0-pub_date"></div>
<tr><th><label for="id_form-0-ORDER">Order:</label></th><td><input type="number" name="form-0-ORDER" value="1" id="id_form-0-ORDER"></td></tr> <div><label for="id_form-0-ORDER">Order:</label><input type="number" name="form-0-ORDER" value="1" id="id_form-0-ORDER"></div>
<tr><th><label for="id_form-1-title">Title:</label></th><td><input type="text" name="form-1-title" value="Article #2" id="id_form-1-title"></td></tr> <div><label for="id_form-1-title">Title:</label><input type="text" name="form-1-title" value="Article #2" id="id_form-1-title"></div>
<tr><th><label for="id_form-1-pub_date">Pub date:</label></th><td><input type="text" name="form-1-pub_date" value="2008-05-11" id="id_form-1-pub_date"></td></tr> <div><label for="id_form-1-pub_date">Pub date:</label><input type="text" name="form-1-pub_date" value="2008-05-11" id="id_form-1-pub_date"></div>
<tr><th><label for="id_form-1-ORDER">Order:</label></th><td><input type="number" name="form-1-ORDER" value="2" id="id_form-1-ORDER"></td></tr> <div><label for="id_form-1-ORDER">Order:</label><input type="number" name="form-1-ORDER" value="2" id="id_form-1-ORDER"></div>
<tr><th><label for="id_form-2-title">Title:</label></th><td><input type="text" name="form-2-title" id="id_form-2-title"></td></tr> <div><label for="id_form-2-title">Title:</label><input type="text" name="form-2-title" id="id_form-2-title"></div>
<tr><th><label for="id_form-2-pub_date">Pub date:</label></th><td><input type="text" name="form-2-pub_date" id="id_form-2-pub_date"></td></tr> <div><label for="id_form-2-pub_date">Pub date:</label><input type="text" name="form-2-pub_date" id="id_form-2-pub_date"></div>
<tr><th><label for="id_form-2-ORDER">Order:</label></th><td><input type="number" name="form-2-ORDER" id="id_form-2-ORDER"></td></tr> <div><label for="id_form-2-ORDER">Order:</label><input type="number" name="form-2-ORDER" id="id_form-2-ORDER"></div>
This adds an additional field to each form. This new field is named ``ORDER`` This adds an additional field to each form. This new field is named ``ORDER``
and is an ``forms.IntegerField``. For the forms that came from the initial and is an ``forms.IntegerField``. For the forms that came from the initial
@ -623,16 +623,16 @@ Lets you create a formset with the ability to select forms for deletion:
... {'title': 'Article #2', 'pub_date': datetime.date(2008, 5, 11)}, ... {'title': 'Article #2', 'pub_date': datetime.date(2008, 5, 11)},
... ]) ... ])
>>> for form in formset: >>> for form in formset:
... print(form.as_table()) ... print(form)
<tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" value="Article #1" id="id_form-0-title"></td></tr> <div><label for="id_form-0-title">Title:</label><input type="text" name="form-0-title" value="Article #1" id="id_form-0-title"></div>
<tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" value="2008-05-10" id="id_form-0-pub_date"></td></tr> <div><label for="id_form-0-pub_date">Pub date:</label><input type="text" name="form-0-pub_date" value="2008-05-10" id="id_form-0-pub_date"></div>
<tr><th><label for="id_form-0-DELETE">Delete:</label></th><td><input type="checkbox" name="form-0-DELETE" id="id_form-0-DELETE"></td></tr> <div><label for="id_form-0-DELETE">Delete:</label><input type="checkbox" name="form-0-DELETE" id="id_form-0-DELETE"></div>
<tr><th><label for="id_form-1-title">Title:</label></th><td><input type="text" name="form-1-title" value="Article #2" id="id_form-1-title"></td></tr> <div><label for="id_form-1-title">Title:</label><input type="text" name="form-1-title" value="Article #2" id="id_form-1-title"></div>
<tr><th><label for="id_form-1-pub_date">Pub date:</label></th><td><input type="text" name="form-1-pub_date" value="2008-05-11" id="id_form-1-pub_date"></td></tr> <div><label for="id_form-1-pub_date">Pub date:</label><input type="text" name="form-1-pub_date" value="2008-05-11" id="id_form-1-pub_date"></div>
<tr><th><label for="id_form-1-DELETE">Delete:</label></th><td><input type="checkbox" name="form-1-DELETE" id="id_form-1-DELETE"></td></tr> <div><label for="id_form-1-DELETE">Delete:</label><input type="checkbox" name="form-1-DELETE" id="id_form-1-DELETE"></div>
<tr><th><label for="id_form-2-title">Title:</label></th><td><input type="text" name="form-2-title" id="id_form-2-title"></td></tr> <div><label for="id_form-2-title">Title:</label><input type="text" name="form-2-title" id="id_form-2-title"></div>
<tr><th><label for="id_form-2-pub_date">Pub date:</label></th><td><input type="text" name="form-2-pub_date" id="id_form-2-pub_date"></td></tr> <div><label for="id_form-2-pub_date">Pub date:</label><input type="text" name="form-2-pub_date" id="id_form-2-pub_date"></div>
<tr><th><label for="id_form-2-DELETE">Delete:</label></th><td><input type="checkbox" name="form-2-DELETE" id="id_form-2-DELETE"></td></tr> <div><label for="id_form-2-DELETE">Delete:</label><input type="checkbox" name="form-2-DELETE" id="id_form-2-DELETE"></div>
Similar to ``can_order`` this adds a new field to each form named ``DELETE`` Similar to ``can_order`` this adds a new field to each form named ``DELETE``
and is a ``forms.BooleanField``. When data comes through marking any of the and is a ``forms.BooleanField``. When data comes through marking any of the
@ -755,10 +755,10 @@ fields/attributes of the order and deletion fields:
>>> ArticleFormSet = formset_factory(ArticleForm, formset=BaseArticleFormSet) >>> ArticleFormSet = formset_factory(ArticleForm, formset=BaseArticleFormSet)
>>> formset = ArticleFormSet() >>> formset = ArticleFormSet()
>>> for form in formset: >>> for form in formset:
... print(form.as_table()) ... print(form)
<tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" id="id_form-0-title"></td></tr> <div><label for="id_form-0-title">Title:</label><input type="text" name="form-0-title" id="id_form-0-title"></div>
<tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" id="id_form-0-pub_date"></td></tr> <div><label for="id_form-0-pub_date">Pub date:</label><input type="text" name="form-0-pub_date" id="id_form-0-pub_date"></div>
<tr><th><label for="id_form-0-my_field">My field:</label></th><td><input type="text" name="form-0-my_field" id="id_form-0-my_field"></td></tr> <div><label for="id_form-0-my_field">My field:</label><input type="text" name="form-0-my_field" id="id_form-0-my_field"></div>
.. _custom-formset-form-kwargs: .. _custom-formset-form-kwargs:

View File

@ -815,13 +815,13 @@ with the ``Author`` model. It works just like a regular formset:
>>> formset = AuthorFormSet() >>> formset = AuthorFormSet()
>>> print(formset) >>> print(formset)
<input type="hidden" name="form-TOTAL_FORMS" value="1" id="id_form-TOTAL_FORMS"><input type="hidden" name="form-INITIAL_FORMS" value="0" id="id_form-INITIAL_FORMS"><input type="hidden" name="form-MIN_NUM_FORMS" value="0" id="id_form-MIN_NUM_FORMS"><input type="hidden" name="form-MAX_NUM_FORMS" value="1000" id="id_form-MAX_NUM_FORMS"> <input type="hidden" name="form-TOTAL_FORMS" value="1" id="id_form-TOTAL_FORMS"><input type="hidden" name="form-INITIAL_FORMS" value="0" id="id_form-INITIAL_FORMS"><input type="hidden" name="form-MIN_NUM_FORMS" value="0" id="id_form-MIN_NUM_FORMS"><input type="hidden" name="form-MAX_NUM_FORMS" value="1000" id="id_form-MAX_NUM_FORMS">
<tr><th><label for="id_form-0-name">Name:</label></th><td><input id="id_form-0-name" type="text" name="form-0-name" maxlength="100"></td></tr> <div><label for="id_form-0-name">Name:</label><input id="id_form-0-name" type="text" name="form-0-name" maxlength="100"></div>
<tr><th><label for="id_form-0-title">Title:</label></th><td><select name="form-0-title" id="id_form-0-title"> <div><label for="id_form-0-title">Title:</label><select name="form-0-title" id="id_form-0-title">
<option value="" selected>---------</option> <option value="" selected>---------</option>
<option value="MR">Mr.</option> <option value="MR">Mr.</option>
<option value="MRS">Mrs.</option> <option value="MRS">Mrs.</option>
<option value="MS">Ms.</option> <option value="MS">Ms.</option>
</select><input type="hidden" name="form-0-id" id="id_form-0-id"></td></tr> </select><input type="hidden" name="form-0-id" id="id_form-0-id"></div>
.. note:: .. note::
@ -1021,11 +1021,11 @@ so long as the total number of forms does not exceed ``max_num``:
>>> AuthorFormSet = modelformset_factory(Author, fields=['name'], max_num=4, extra=2) >>> AuthorFormSet = modelformset_factory(Author, fields=['name'], max_num=4, extra=2)
>>> formset = AuthorFormSet(queryset=Author.objects.order_by('name')) >>> formset = AuthorFormSet(queryset=Author.objects.order_by('name'))
>>> for form in formset: >>> for form in formset:
... print(form.as_table()) ... print(form)
<tr><th><label for="id_form-0-name">Name:</label></th><td><input id="id_form-0-name" type="text" name="form-0-name" value="Charles Baudelaire" maxlength="100"><input type="hidden" name="form-0-id" value="1" id="id_form-0-id"></td></tr> <div><label for="id_form-0-name">Name:</label><input id="id_form-0-name" type="text" name="form-0-name" value="Charles Baudelaire" maxlength="100"><input type="hidden" name="form-0-id" value="1" id="id_form-0-id"></div>
<tr><th><label for="id_form-1-name">Name:</label></th><td><input id="id_form-1-name" type="text" name="form-1-name" value="Paul Verlaine" maxlength="100"><input type="hidden" name="form-1-id" value="3" id="id_form-1-id"></td></tr> <div><label for="id_form-1-name">Name:</label><input id="id_form-1-name" type="text" name="form-1-name" value="Paul Verlaine" maxlength="100"><input type="hidden" name="form-1-id" value="3" id="id_form-1-id"></div>
<tr><th><label for="id_form-2-name">Name:</label></th><td><input id="id_form-2-name" type="text" name="form-2-name" value="Walt Whitman" maxlength="100"><input type="hidden" name="form-2-id" value="2" id="id_form-2-id"></td></tr> <div><label for="id_form-2-name">Name:</label><input id="id_form-2-name" type="text" name="form-2-name" value="Walt Whitman" maxlength="100"><input type="hidden" name="form-2-id" value="2" id="id_form-2-id"></div>
<tr><th><label for="id_form-3-name">Name:</label></th><td><input id="id_form-3-name" type="text" name="form-3-name" maxlength="100"><input type="hidden" name="form-3-id" id="id_form-3-id"></td></tr> <div><label for="id_form-3-name">Name:</label><input id="id_form-3-name" type="text" name="form-3-name" maxlength="100"><input type="hidden" name="form-3-id" id="id_form-3-id"></div>
A ``max_num`` value of ``None`` (the default) puts a high limit on the number A ``max_num`` value of ``None`` (the default) puts a high limit on the number
of forms displayed (1000). In practice this is equivalent to no limit. of forms displayed (1000). In practice this is equivalent to no limit.