summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Dufresne <jon.dufresne@gmail.com>2016-03-28 11:02:04 -0700
committerTim Graham <timograham@gmail.com>2016-04-21 19:16:38 -0400
commitec6121693f112ae33b653b4364e812722d2eb567 (patch)
treeb791f1345a114d07657a3d226d1c5ff4b1e3f369
parent4d1c229ee5cb210e8b592a8d9c87d4a66864328e (diff)
Fixed #22383 -- Added support for HTML5 required attribute on required form fields.
-rw-r--r--django/forms/boundfield.py2
-rw-r--r--django/forms/forms.py6
-rw-r--r--django/forms/formsets.py5
-rw-r--r--django/forms/models.py8
-rw-r--r--docs/ref/forms/api.txt189
-rw-r--r--docs/ref/forms/fields.txt44
-rw-r--r--docs/ref/forms/widgets.txt30
-rw-r--r--docs/releases/1.10.txt11
-rw-r--r--docs/topics/forms/formsets.txt5
-rw-r--r--docs/topics/forms/index.txt8
-rw-r--r--tests/admin_views/tests.py2
-rw-r--r--tests/forms_tests/field_tests/test_charfield.py2
-rw-r--r--tests/forms_tests/field_tests/test_choicefield.py2
-rw-r--r--tests/forms_tests/field_tests/test_decimalfield.py11
-rw-r--r--tests/forms_tests/field_tests/test_durationfield.py2
-rw-r--r--tests/forms_tests/field_tests/test_emailfield.py7
-rw-r--r--tests/forms_tests/field_tests/test_floatfield.py14
-rw-r--r--tests/forms_tests/field_tests/test_integerfield.py10
-rw-r--r--tests/forms_tests/field_tests/test_multivaluefield.py16
-rw-r--r--tests/forms_tests/field_tests/test_urlfield.py4
-rw-r--r--tests/forms_tests/tests/test_forms.py909
-rw-r--r--tests/forms_tests/tests/test_regressions.py22
-rw-r--r--tests/forms_tests/tests/tests.py26
-rw-r--r--tests/i18n/tests.py20
-rw-r--r--tests/model_forms/tests.py139
-rw-r--r--tests/model_formsets/tests.py4
-rw-r--r--tests/modeladmin/tests.py4
-rw-r--r--tests/postgres_tests/test_array.py6
28 files changed, 849 insertions, 659 deletions
diff --git a/django/forms/boundfield.py b/django/forms/boundfield.py
index 6567c4f08f..4867e72deb 100644
--- a/django/forms/boundfield.py
+++ b/django/forms/boundfield.py
@@ -85,6 +85,8 @@ class BoundField(object):
widget.is_localized = True
attrs = attrs or {}
+ if not widget.is_hidden and self.field.required and self.form.use_required_attribute:
+ attrs['required'] = True
if self.field.disabled:
attrs['disabled'] = True
auto_id = self.auto_id
diff --git a/django/forms/forms.py b/django/forms/forms.py
index ac5cf12425..e2ed1a4ac1 100644
--- a/django/forms/forms.py
+++ b/django/forms/forms.py
@@ -67,10 +67,11 @@ class BaseForm(object):
# class, not to the Form class.
field_order = None
prefix = None
+ use_required_attribute = True
def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
initial=None, error_class=ErrorList, label_suffix=None,
- empty_permitted=False, field_order=None):
+ empty_permitted=False, field_order=None, use_required_attribute=None):
self.is_bound = data is not None or files is not None
self.data = data or {}
self.files = files or {}
@@ -93,6 +94,9 @@ class BaseForm(object):
self._bound_fields_cache = {}
self.order_fields(self.field_order if field_order is None else field_order)
+ if use_required_attribute is not None:
+ self.use_required_attribute = use_required_attribute
+
def order_fields(self, field_order):
"""
Rearranges the fields according to field_order.
diff --git a/django/forms/formsets.py b/django/forms/formsets.py
index 6400e4a67f..166a6adaeb 100644
--- a/django/forms/formsets.py
+++ b/django/forms/formsets.py
@@ -161,6 +161,10 @@ class BaseFormSet(object):
'auto_id': self.auto_id,
'prefix': self.add_prefix(i),
'error_class': self.error_class,
+ # Don't render the HTML 'required' attribute as it may cause
+ # incorrect validation for extra, optional, and deleted
+ # forms in the formset.
+ 'use_required_attribute': False,
}
if self.is_bound:
defaults['data'] = self.data
@@ -195,6 +199,7 @@ class BaseFormSet(object):
auto_id=self.auto_id,
prefix=self.add_prefix('__prefix__'),
empty_permitted=True,
+ use_required_attribute=False,
**self.get_form_kwargs(None)
)
self.add_fields(form, None)
diff --git a/django/forms/models.py b/django/forms/models.py
index aac75b54ff..4ed8b746d9 100644
--- a/django/forms/models.py
+++ b/django/forms/models.py
@@ -278,7 +278,7 @@ class ModelFormMetaclass(DeclarativeFieldsMetaclass):
class BaseModelForm(BaseForm):
def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
initial=None, error_class=ErrorList, label_suffix=None,
- empty_permitted=False, instance=None):
+ empty_permitted=False, instance=None, use_required_attribute=None):
opts = self._meta
if opts.model is None:
raise ValueError('ModelForm has no model class specified.')
@@ -296,8 +296,10 @@ class BaseModelForm(BaseForm):
# It is False by default so overriding self.clean() and failing to call
# super will stop validate_unique from being called.
self._validate_unique = False
- super(BaseModelForm, self).__init__(data, files, auto_id, prefix, object_data,
- error_class, label_suffix, empty_permitted)
+ super(BaseModelForm, self).__init__(
+ data, files, auto_id, prefix, object_data, error_class,
+ label_suffix, empty_permitted, use_required_attribute=use_required_attribute,
+ )
# Apply ``limit_choices_to`` to each field.
for field_name in self.fields:
formfield = self.fields[field_name]
diff --git a/docs/ref/forms/api.txt b/docs/ref/forms/api.txt
index f1c46da947..c468dc38a0 100644
--- a/docs/ref/forms/api.txt
+++ b/docs/ref/forms/api.txt
@@ -244,9 +244,9 @@ precedence::
... comment = forms.CharField()
>>> f = CommentForm(initial={'name': 'instance'}, auto_id=False)
>>> print(f)
- <tr><th>Name:</th><td><input type="text" name="name" value="instance" /></td></tr>
- <tr><th>Url:</th><td><input type="url" name="url" /></td></tr>
- <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
+ <tr><th>Name:</th><td><input type="text" name="name" value="instance" required /></td></tr>
+ <tr><th>Url:</th><td><input type="url" name="url" required /></td></tr>
+ <tr><th>Comment:</th><td><input type="text" name="comment" required /></td></tr>
Checking which form data has changed
====================================
@@ -305,10 +305,10 @@ You can alter the field of :class:`Form` instance to change the way it is
presented in the form::
>>> f.as_table().split('\n')[0]
- '<tr><th>Name:</th><td><input name="name" type="text" value="instance" /></td></tr>'
+ '<tr><th>Name:</th><td><input name="name" type="text" value="instance" required /></td></tr>'
>>> f.fields['name'].label = "Username"
>>> f.as_table().split('\n')[0]
- '<tr><th>Username:</th><td><input name="name" type="text" value="instance" /></td></tr>'
+ '<tr><th>Username:</th><td><input name="name" type="text" value="instance" required /></td></tr>'
Beware not to alter the ``base_fields`` attribute because this modification
will influence all subsequent ``ContactForm`` instances within the same Python
@@ -317,7 +317,7 @@ process::
>>> f.base_fields['name'].label = "Username"
>>> another_f = CommentForm(auto_id=False)
>>> another_f.as_table().split('\n')[0]
- '<tr><th>Username:</th><td><input name="name" type="text" value="class" /></td></tr>'
+ '<tr><th>Username:</th><td><input name="name" type="text" value="class" required /></td></tr>'
Accessing "clean" data
======================
@@ -421,9 +421,9 @@ simply ``print`` it::
>>> f = ContactForm()
>>> print(f)
- <tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" /></td></tr>
- <tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" /></td></tr>
- <tr><th><label for="id_sender">Sender:</label></th><td><input type="email" name="sender" id="id_sender" /></td></tr>
+ <tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" required /></td></tr>
+ <tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" required /></td></tr>
+ <tr><th><label for="id_sender">Sender:</label></th><td><input type="email" name="sender" id="id_sender" required /></td></tr>
<tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" /></td></tr>
If the form is bound to data, the HTML output will include that data
@@ -438,9 +438,9 @@ include ``checked="checked"`` if appropriate::
... 'cc_myself': True}
>>> f = ContactForm(data)
>>> print(f)
- <tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" value="hello" /></td></tr>
- <tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" value="Hi there" /></td></tr>
- <tr><th><label for="id_sender">Sender:</label></th><td><input type="email" name="sender" id="id_sender" value="foo@example.com" /></td></tr>
+ <tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" value="hello" required /></td></tr>
+ <tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" value="Hi there" required /></td></tr>
+ <tr><th><label for="id_sender">Sender:</label></th><td><input type="email" name="sender" id="id_sender" value="foo@example.com" required /></td></tr>
<tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" checked="checked" /></td></tr>
This default output is a two-column HTML table, with a ``<tr>`` for each field.
@@ -485,11 +485,11 @@ containing one field::
>>> f = ContactForm()
>>> f.as_p()
- '<p><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" /></p>\n<p><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></p>\n<p><label for="id_sender">Sender:</label> <input type="text" name="sender" id="id_sender" /></p>\n<p><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></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" /></p>
- <p><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></p>
- <p><label for="id_sender">Sender:</label> <input type="email" name="sender" id="id_sender" /></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()``
@@ -504,11 +504,11 @@ flexibility::
>>> f = ContactForm()
>>> f.as_ul()
- '<li><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" /></li>\n<li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></li>\n<li><label for="id_sender">Sender:</label> <input type="email" name="sender" id="id_sender" /></li>\n<li><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></li>'
+ '<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" /></li>
- <li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></li>
- <li><label for="id_sender">Sender:</label> <input type="email" name="sender" id="id_sender" /></li>
+ <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()``
@@ -522,11 +522,11 @@ it calls its ``as_table()`` method behind the scenes::
>>> f = ContactForm()
>>> f.as_table()
- '<tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" /></td></tr>\n<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" /></td></tr>\n<tr><th><label for="id_sender">Sender:</label></th><td><input type="email" name="sender" id="id_sender" /></td></tr>\n<tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" /></td></tr>'
+ '<tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" required /></td></tr>\n<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" required /></td></tr>\n<tr><th><label for="id_sender">Sender:</label></th><td><input type="email" name="sender" id="id_sender" required /></td></tr>\n<tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" /></td></tr>'
>>> print(f.as_table())
- <tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" /></td></tr>
- <tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" /></td></tr>
- <tr><th><label for="id_sender">Sender:</label></th><td><input type="email" name="sender" id="id_sender" /></td></tr>
+ <tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" required /></td></tr>
+ <tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" required /></td></tr>
+ <tr><th><label for="id_sender">Sender:</label></th><td><input type="email" name="sender" id="id_sender" required /></td></tr>
<tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" /></td></tr>
.. _ref-forms-api-styling-form-rows:
@@ -597,19 +597,19 @@ tags nor ``id`` attributes::
>>> f = ContactForm(auto_id=False)
>>> print(f.as_table())
- <tr><th>Subject:</th><td><input type="text" name="subject" maxlength="100" /></td></tr>
- <tr><th>Message:</th><td><input type="text" name="message" /></td></tr>
- <tr><th>Sender:</th><td><input type="email" name="sender" /></td></tr>
+ <tr><th>Subject:</th><td><input type="text" name="subject" maxlength="100" required /></td></tr>
+ <tr><th>Message:</th><td><input type="text" name="message" required /></td></tr>
+ <tr><th>Sender:</th><td><input type="email" name="sender" required /></td></tr>
<tr><th>Cc myself:</th><td><input type="checkbox" name="cc_myself" /></td></tr>
>>> print(f.as_ul())
- <li>Subject: <input type="text" name="subject" maxlength="100" /></li>
- <li>Message: <input type="text" name="message" /></li>
- <li>Sender: <input type="email" name="sender" /></li>
+ <li>Subject: <input type="text" name="subject" maxlength="100" required /></li>
+ <li>Message: <input type="text" name="message" required /></li>
+ <li>Sender: <input type="email" name="sender" required /></li>
<li>Cc myself: <input type="checkbox" name="cc_myself" /></li>
>>> print(f.as_p())
- <p>Subject: <input type="text" name="subject" maxlength="100" /></p>
- <p>Message: <input type="text" name="message" /></p>
- <p>Sender: <input type="email" name="sender" /></p>
+ <p>Subject: <input type="text" name="subject" maxlength="100" required /></p>
+ <p>Message: <input type="text" name="message" required /></p>
+ <p>Sender: <input type="email" name="sender" required /></p>
<p>Cc myself: <input type="checkbox" name="cc_myself" /></p>
If ``auto_id`` is set to ``True``, then the form output *will* include
@@ -618,19 +618,19 @@ field::
>>> f = ContactForm(auto_id=True)
>>> print(f.as_table())
- <tr><th><label for="subject">Subject:</label></th><td><input id="subject" type="text" name="subject" maxlength="100" /></td></tr>
- <tr><th><label for="message">Message:</label></th><td><input type="text" name="message" id="message" /></td></tr>
- <tr><th><label for="sender">Sender:</label></th><td><input type="email" name="sender" id="sender" /></td></tr>
+ <tr><th><label for="subject">Subject:</label></th><td><input id="subject" type="text" name="subject" maxlength="100" required /></td></tr>
+ <tr><th><label for="message">Message:</label></th><td><input type="text" name="message" id="message" required /></td></tr>
+ <tr><th><label for="sender">Sender:</label></th><td><input type="email" name="sender" id="sender" required /></td></tr>
<tr><th><label for="cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="cc_myself" /></td></tr>
>>> print(f.as_ul())
- <li><label for="subject">Subject:</label> <input id="subject" type="text" name="subject" maxlength="100" /></li>
- <li><label for="message">Message:</label> <input type="text" name="message" id="message" /></li>
- <li><label for="sender">Sender:</label> <input type="email" name="sender" id="sender" /></li>
+ <li><label for="subject">Subject:</label> <input id="subject" type="text" name="subject" maxlength="100" required /></li>
+ <li><label for="message">Message:</label> <input type="text" name="message" id="message" required /></li>
+ <li><label for="sender">Sender:</label> <input type="email" name="sender" id="sender" required /></li>
<li><label for="cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="cc_myself" /></li>
>>> print(f.as_p())
- <p><label for="subject">Subject:</label> <input id="subject" type="text" name="subject" maxlength="100" /></p>
- <p><label for="message">Message:</label> <input type="text" name="message" id="message" /></p>
- <p><label for="sender">Sender:</label> <input type="email" name="sender" id="sender" /></p>
+ <p><label for="subject">Subject:</label> <input id="subject" type="text" name="subject" maxlength="100" required /></p>
+ <p><label for="message">Message:</label> <input type="text" name="message" id="message" required /></p>
+ <p><label for="sender">Sender:</label> <input type="email" name="sender" id="sender" required /></p>
<p><label for="cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="cc_myself" /></p>
If ``auto_id`` is set to a string containing the format character ``'%s'``,
@@ -641,19 +641,19 @@ attributes based on the format string. For example, for a format string
>>> f = ContactForm(auto_id='id_for_%s')
>>> print(f.as_table())
- <tr><th><label for="id_for_subject">Subject:</label></th><td><input id="id_for_subject" type="text" name="subject" maxlength="100" /></td></tr>
- <tr><th><label for="id_for_message">Message:</label></th><td><input type="text" name="message" id="id_for_message" /></td></tr>
- <tr><th><label for="id_for_sender">Sender:</label></th><td><input type="email" name="sender" id="id_for_sender" /></td></tr>
+ <tr><th><label for="id_for_subject">Subject:</label></th><td><input id="id_for_subject" type="text" name="subject" maxlength="100" required /></td></tr>
+ <tr><th><label for="id_for_message">Message:</label></th><td><input type="text" name="message" id="id_for_message" required /></td></tr>
+ <tr><th><label for="id_for_sender">Sender:</label></th><td><input type="email" name="sender" id="id_for_sender" required /></td></tr>
<tr><th><label for="id_for_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></td></tr>
>>> print(f.as_ul())
- <li><label for="id_for_subject">Subject:</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" /></li>
- <li><label for="id_for_message">Message:</label> <input type="text" name="message" id="id_for_message" /></li>
- <li><label for="id_for_sender">Sender:</label> <input type="email" name="sender" id="id_for_sender" /></li>
+ <li><label for="id_for_subject">Subject:</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" required /></li>
+ <li><label for="id_for_message">Message:</label> <input type="text" name="message" id="id_for_message" required /></li>
+ <li><label for="id_for_sender">Sender:</label> <input type="email" name="sender" id="id_for_sender" required /></li>
<li><label for="id_for_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></li>
>>> print(f.as_p())
- <p><label for="id_for_subject">Subject:</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" /></p>
- <p><label for="id_for_message">Message:</label> <input type="text" name="message" id="id_for_message" /></p>
- <p><label for="id_for_sender">Sender:</label> <input type="email" name="sender" id="id_for_sender" /></p>
+ <p><label for="id_for_subject">Subject:</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" required /></p>
+ <p><label for="id_for_message">Message:</label> <input type="text" name="message" id="id_for_message" required /></p>
+ <p><label for="id_for_sender">Sender:</label> <input type="email" name="sender" id="id_for_sender" required /></p>
<p><label for="id_for_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></p>
If ``auto_id`` is set to any other true value -- such as a string that doesn't
@@ -671,15 +671,15 @@ It's possible to customize that character, or omit it entirely, using the
>>> f = ContactForm(auto_id='id_for_%s', label_suffix='')
>>> print(f.as_ul())
- <li><label for="id_for_subject">Subject</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" /></li>
- <li><label for="id_for_message">Message</label> <input type="text" name="message" id="id_for_message" /></li>
- <li><label for="id_for_sender">Sender</label> <input type="email" name="sender" id="id_for_sender" /></li>
+ <li><label for="id_for_subject">Subject</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" required /></li>
+ <li><label for="id_for_message">Message</label> <input type="text" name="message" id="id_for_message" required /></li>
+ <li><label for="id_for_sender">Sender</label> <input type="email" name="sender" id="id_for_sender" required /></li>
<li><label for="id_for_cc_myself">Cc myself</label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></li>
>>> f = ContactForm(auto_id='id_for_%s', label_suffix=' ->')
>>> print(f.as_ul())
- <li><label for="id_for_subject">Subject -></label> <input id="id_for_subject" type="text" name="subject" maxlength="100" /></li>
- <li><label for="id_for_message">Message -></label> <input type="text" name="message" id="id_for_message" /></li>
- <li><label for="id_for_sender">Sender -></label> <input type="email" name="sender" id="id_for_sender" /></li>
+ <li><label for="id_for_subject">Subject -></label> <input id="id_for_subject" type="text" name="subject" maxlength="100" required /></li>
+ <li><label for="id_for_message">Message -></label> <input type="text" name="message" id="id_for_message" required /></li>
+ <li><label for="id_for_sender">Sender -></label> <input type="email" name="sender" id="id_for_sender" required /></li>
<li><label for="id_for_cc_myself">Cc myself -></label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></li>
Note that the label suffix is added only if the last character of the
@@ -692,6 +692,17 @@ This will take precedence over :attr:`Form.label_suffix
using the ``label_suffix`` parameter to
:meth:`~django.forms.BoundField.label_tag`.
+.. attribute:: Form.use_required_attribute
+
+.. versionadded:: 1.10
+
+When set to ``True`` (the default), required form fields will have the
+``required`` HTML attribute.
+
+:doc:`Formsets </topics/forms/formsets>` instantiate forms with
+``use_required_attribute=False`` to avoid incorrect browser validation when
+adding and deleting forms from a formset.
+
Notes on field ordering
-----------------------
@@ -741,21 +752,21 @@ method you're using::
... 'cc_myself': True}
>>> f = ContactForm(data, auto_id=False)
>>> print(f.as_table())
- <tr><th>Subject:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="subject" maxlength="100" /></td></tr>
- <tr><th>Message:</th><td><input type="text" name="message" value="Hi there" /></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" /></td></tr>
+ <tr><th>Subject:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="subject" maxlength="100" required /></td></tr>
+ <tr><th>Message:</th><td><input type="text" name="message" value="Hi there" required /></td></tr>
+ <tr><th>Sender:</th><td><ul class="errorlist"><li>Enter a valid email address.</li></ul><input type="email" name="sender" value="invalid email address" required /></td></tr>
<tr><th>Cc myself:</th><td><input checked="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" /></li>
- <li>Message: <input type="text" name="message" value="Hi there" /></li>
- <li><ul class="errorlist"><li>Enter a valid email address.</li></ul>Sender: <input type="email" name="sender" value="invalid email address" /></li>
+ <li><ul class="errorlist"><li>This field is required.</li></ul>Subject: <input type="text" name="subject" maxlength="100" required /></li>
+ <li>Message: <input type="text" name="message" value="Hi there" required /></li>
+ <li><ul class="errorlist"><li>Enter a valid email address.</li></ul>Sender: <input type="email" name="sender" value="invalid email address" required /></li>
<li>Cc myself: <input checked="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" /></p>
- <p>Message: <input type="text" name="message" value="Hi there" /></p>
+ <p>Subject: <input type="text" name="subject" maxlength="100" required /></p>
+ <p>Message: <input type="text" name="message" value="Hi there" required /></p>
<p><ul class="errorlist"><li>Enter a valid email address.</li></ul></p>
- <p>Sender: <input type="email" name="sender" value="invalid email address" /></p>
+ <p>Sender: <input type="email" name="sender" value="invalid email address" required /></p>
<p>Cc myself: <input checked="checked" type="checkbox" name="cc_myself" /></p>
.. _ref-forms-error-list-format:
@@ -778,10 +789,10 @@ Python 2)::
>>> f = ContactForm(data, auto_id=False, error_class=DivErrorList)
>>> f.as_p()
<div class="errorlist"><div class="error">This field is required.</div></div>
- <p>Subject: <input type="text" name="subject" maxlength="100" /></p>
- <p>Message: <input type="text" name="message" value="Hi there" /></p>
+ <p>Subject: <input type="text" name="subject" maxlength="100" required /></p>
+ <p>Message: <input type="text" name="message" value="Hi there" required /></p>
<div class="errorlist"><div class="error">Enter a valid email address.</div></div>
- <p>Sender: <input type="email" name="sender" value="invalid email address" /></p>
+ <p>Sender: <input type="email" name="sender" value="invalid email address" required /></p>
<p>Cc myself: <input checked="checked" type="checkbox" name="cc_myself" /></p>
More granular output
@@ -803,25 +814,25 @@ using the field's name as the key::
>>> form = ContactForm()
>>> print(form['subject'])
- <input id="id_subject" type="text" name="subject" maxlength="100" />
+ <input id="id_subject" type="text" name="subject" maxlength="100" required />
To retrieve all ``BoundField`` objects, iterate the form::
>>> form = ContactForm()
>>> for boundfield in form: print(boundfield)
- <input id="id_subject" type="text" name="subject" maxlength="100" />
- <input type="text" name="message" id="id_message" />
- <input type="email" name="sender" id="id_sender" />
+ <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" />
The field-specific output honors the form object's ``auto_id`` setting::
>>> f = ContactForm(auto_id=False)
>>> print(f['message'])
- <input type="text" name="message" />
+ <input type="text" name="message" required />
>>> f = ContactForm(auto_id='id_%s')
>>> print(f['message'])
- <input type="text" name="message" id="id_message" />
+ <input type="text" name="message" id="id_message" required />
Attributes of ``BoundField``
----------------------------
@@ -852,7 +863,7 @@ Attributes of ``BoundField``
>>> data = {'subject': 'hi', 'message': '', 'sender': '', 'cc_myself': ''}
>>> f = ContactForm(data, auto_id=False)
>>> print(f['message'])
- <input type="text" name="message" />
+ <input type="text" name="message" required />
>>> f['message'].errors
['This field is required.']
>>> print(f['message'].errors)
@@ -904,7 +915,7 @@ Attributes of ``BoundField``
.. code-block:: html
- <label for="myFIELD">...</label><input id="myFIELD" type="text" name="my_field" />
+ <label for="myFIELD">...</label><input id="myFIELD" type="text" name="my_field" required />
.. attribute:: BoundField.is_hidden
@@ -1125,11 +1136,11 @@ fields are ordered first::
... priority = forms.CharField()
>>> f = ContactFormWithPriority(auto_id=False)
>>> print(f.as_ul())
- <li>Subject: <input type="text" name="subject" maxlength="100" /></li>
- <li>Message: <input type="text" name="message" /></li>
- <li>Sender: <input type="email" name="sender" /></li>
+ <li>Subject: <input type="text" name="subject" maxlength="100" required /></li>
+ <li>Message: <input type="text" name="message" required /></li>
+ <li>Sender: <input type="email" name="sender" required /></li>
<li>Cc myself: <input type="checkbox" name="cc_myself" /></li>
- <li>Priority: <input type="text" name="priority" /></li>
+ <li>Priority: <input type="text" name="priority" required /></li>
It's possible to subclass multiple forms, treating forms as mixins. In this
example, ``BeatleForm`` subclasses both ``PersonForm`` and ``InstrumentForm``
@@ -1146,10 +1157,10 @@ classes::
... haircut_type = CharField()
>>> b = BeatleForm(auto_id=False)
>>> print(b.as_ul())
- <li>First name: <input type="text" name="first_name" /></li>
- <li>Last name: <input type="text" name="last_name" /></li>
- <li>Instrument: <input type="text" name="instrument" /></li>
- <li>Haircut type: <input type="text" name="haircut_type" /></li>
+ <li>First name: <input type="text" name="first_name" required /></li>
+ <li>Last name: <input type="text" name="last_name" required /></li>
+ <li>Instrument: <input type="text" name="instrument" required /></li>
+ <li>Haircut type: <input type="text" name="haircut_type" required /></li>
It's possible to declaratively remove a ``Field`` inherited from a parent class
by setting the name of the field to ``None`` on the subclass. For example::
@@ -1179,11 +1190,11 @@ You can put several Django forms inside one ``<form>`` tag. To give each
>>> mother = PersonForm(prefix="mother")
>>> father = PersonForm(prefix="father")
>>> print(mother.as_ul())
- <li><label for="id_mother-first_name">First name:</label> <input type="text" name="mother-first_name" id="id_mother-first_name" /></li>
- <li><label for="id_mother-last_name">Last name:</label> <input type="text" name="mother-last_name" id="id_mother-last_name" /></li>
+ <li><label for="id_mother-first_name">First name:</label> <input type="text" name="mother-first_name" id="id_mother-first_name" required /></li>
+ <li><label for="id_mother-last_name">Last name:</label> <input type="text" name="mother-last_name" id="id_mother-last_name" required /></li>
>>> print(father.as_ul())
- <li><label for="id_father-first_name">First name:</label> <input type="text" name="father-first_name" id="id_father-first_name" /></li>
- <li><label for="id_father-last_name">Last name:</label> <input type="text" name="father-last_name" id="id_father-last_name" /></li>
+ <li><label for="id_father-first_name">First name:</label> <input type="text" name="father-first_name" id="id_father-first_name" required /></li>
+ <li><label for="id_father-last_name">Last name:</label> <input type="text" name="father-last_name" id="id_father-last_name" required /></li>
The prefix can also be specified on the form class::
diff --git a/docs/ref/forms/fields.txt b/docs/ref/forms/fields.txt
index 1748262de4..f21bae462a 100644
--- a/docs/ref/forms/fields.txt
+++ b/docs/ref/forms/fields.txt
@@ -115,9 +115,9 @@ We've specified ``auto_id=False`` to simplify the output::
... comment = forms.CharField()
>>> f = CommentForm(auto_id=False)
>>> print(f)
- <tr><th>Your name:</th><td><input type="text" name="name" /></td></tr>
- <tr><th>Your website:</th><td><input type="url" name="url" /></td></tr>
- <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
+ <tr><th>Your name:</th><td><input type="text" name="name" required /></td></tr>
+ <tr><th>Your website:</th><td><input type="url" name="url" required /></td></tr>
+ <tr><th>Comment:</th><td><input type="text" name="comment" required /></td></tr>
``label_suffix``
----------------
@@ -133,9 +133,9 @@ The ``label_suffix`` argument lets you override the form's
... captcha_answer = forms.IntegerField(label='2 + 2', label_suffix=' =')
>>> f = ContactForm(label_suffix='?')
>>> print(f.as_p())
- <p><label for="id_age">Age?</label> <input id="id_age" name="age" type="number" /></p>
- <p><label for="id_nationality">Nationality?</label> <input id="id_nationality" name="nationality" type="text" /></p>
- <p><label for="id_captcha_answer">2 + 2 =</label> <input id="id_captcha_answer" name="captcha_answer" type="number" /></p>
+ <p><label for="id_age">Age?</label> <input id="id_age" name="age" type="number" required /></p>
+ <p><label for="id_nationality">Nationality?</label> <input id="id_nationality" name="nationality" type="text" required /></p>
+ <p><label for="id_captcha_answer">2 + 2 =</label> <input id="id_captcha_answer" name="captcha_answer" type="number" required /></p>
``initial``
-----------
@@ -157,9 +157,9 @@ field is initialized to a particular value. For example::
... comment = forms.CharField()
>>> f = CommentForm(auto_id=False)
>>> print(f)
- <tr><th>Name:</th><td><input type="text" name="name" value="Your name" /></td></tr>
- <tr><th>Url:</th><td><input type="url" name="url" value="http://" /></td></tr>
- <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
+ <tr><th>Name:</th><td><input type="text" name="name" value="Your name" required /></td></tr>
+ <tr><th>Url:</th><td><input type="url" name="url" value="http://" required /></td></tr>
+ <tr><th>Comment:</th><td><input type="text" name="comment" required /></td></tr>
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,
@@ -172,9 +172,9 @@ and the HTML output will include any validation errors::
>>> default_data = {'name': 'Your name', 'url': 'http://'}
>>> f = CommentForm(default_data, auto_id=False)
>>> print(f)
- <tr><th>Name:</th><td><input type="text" name="name" value="Your name" /></td></tr>
- <tr><th>Url:</th><td><ul class="errorlist"><li>Enter a valid URL.</li></ul><input type="url" name="url" value="http://" /></td></tr>
- <tr><th>Comment:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="comment" /></td></tr>
+ <tr><th>Name:</th><td><input type="text" name="name" value="Your name" required /></td></tr>
+ <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>
+ <tr><th>Comment:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="comment" required /></td></tr>
This is why ``initial`` values are only displayed for unbound forms. For bound
forms, the HTML output will use the bound data.
@@ -201,7 +201,7 @@ Instead of a constant, you can also pass any callable::
>>> class DateForm(forms.Form):
... day = forms.DateField(initial=datetime.date.today)
>>> print(DateForm())
- <tr><th>Day:</th><td><input type="text" name="day" value="12/23/2008" /><td></tr>
+ <tr><th>Day:</th><td><input type="text" name="day" value="12/23/2008" required /><td></tr>
The callable will be evaluated only when the unbound form is displayed, not when it is defined.
@@ -237,19 +237,19 @@ fields. We've specified ``auto_id=False`` to simplify the output::
... cc_myself = forms.BooleanField(required=False)
>>> f = HelpTextContactForm(auto_id=False)
>>> print(f.as_table())
- <tr><th>Subject:</th><td><input type="text" name="subject" maxlength="100" /><br /><span class="helptext">100 characters max.</span></td></tr>
- <tr><th>Message:</th><td><input type="text" name="message" /></td></tr>
- <tr><th>Sender:</th><td><input type="email" name="sender" /><br />A valid email address, please.</td></tr>
+ <tr><th>Subject:</th><td><input type="text" name="subject" maxlength="100" required /><br /><span class="helptext">100 characters max.</span></td></tr>
+ <tr><th>Message:</th><td><input type="text" name="message" required /></td></tr>
+ <tr><th>Sender:</th><td><input type="email" name="sender" required /><br />A valid email address, please.</td></tr>
<tr><th>Cc myself:</th><td><input type="checkbox" name="cc_myself" /></td></tr>
>>> print(f.as_ul()))
- <li>Subject: <input type="text" name="subject" maxlength="100" /> <span class="helptext">100 characters max.</span></li>
- <li>Message: <input type="text" name="message" /></li>
- <li>Sender: <input type="email" name="sender" /> A valid email address, please.</li>
+ <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" /> <span class="helptext">100 characters max.</span></p>
- <p>Message: <input type="text" name="message" /></p>
- <p>Sender: <input type="email" name="sender" /> A valid email address, please.</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``
diff --git a/docs/ref/forms/widgets.txt b/docs/ref/forms/widgets.txt
index e347876724..f2b132ce3d 100644
--- a/docs/ref/forms/widgets.txt
+++ b/docs/ref/forms/widgets.txt
@@ -135,9 +135,9 @@ provided for each widget will be rendered exactly the same::
>>> f = CommentForm(auto_id=False)
>>> f.as_table()
- <tr><th>Name:</th><td><input type="text" name="name" /></td></tr>
- <tr><th>Url:</th><td><input type="url" name="url"/></td></tr>
- <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
+ <tr><th>Name:</th><td><input type="text" name="name" required /></td></tr>
+ <tr><th>Url:</th><td><input type="url" name="url" required /></td></tr>
+ <tr><th>Comment:</th><td><input type="text" name="comment" required /></td></tr>
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
@@ -154,9 +154,9 @@ Django will then include the extra attributes in the rendered output:
>>> f = CommentForm(auto_id=False)
>>> f.as_table()
- <tr><th>Name:</th><td><input type="text" name="name" class="special"/></td></tr>
- <tr><th>Url:</th><td><input type="url" name="url"/></td></tr>
- <tr><th>Comment:</th><td><input type="text" name="comment" size="40"/></td></tr>
+ <tr><th>Name:</th><td><input type="text" name="name" class="special" required /></td></tr>
+ <tr><th>Url:</th><td><input type="url" name="url" required /></td></tr>
+ <tr><th>Comment:</th><td><input type="text" name="comment" size="40" required /></td></tr>
You can also set the HTML ``id`` using :attr:`~Widget.attrs`. See
:attr:`BoundField.id_for_label` for an example.
@@ -204,7 +204,7 @@ foundation for custom widgets.
>>> from django import forms
>>> name = forms.TextInput(attrs={'size': 10, 'title': 'Your name',})
>>> name.render('name', 'A name')
- '<input title="Your name" type="text" name="name" value="A name" size="10" />'
+ '<input title="Your name" type="text" name="name" value="A name" size="10" required />'
If you assign a value of ``True`` or ``False`` to an attribute,
it will be rendered as an HTML5 boolean attribute::
@@ -627,16 +627,16 @@ Selector and checkbox widgets
.. code-block:: html
<div class="myradio">
- <label for="id_beatles_0"><input id="id_beatles_0" name="beatles" type="radio" value="john" /> John</label>
+ <label for="id_beatles_0"><input id="id_beatles_0" name="beatles" type="radio" value="john" required /> John</label>
</div>
<div class="myradio">
- <label for="id_beatles_1"><input id="id_beatles_1" name="beatles" type="radio" value="paul" /> Paul</label>
+ <label for="id_beatles_1"><input id="id_beatles_1" name="beatles" type="radio" value="paul" required /> Paul</label>
</div>
<div class="myradio">
- <label for="id_beatles_2"><input id="id_beatles_2" name="beatles" type="radio" value="george" /> George</label>
+ <label for="id_beatles_2"><input id="id_beatles_2" name="beatles" type="radio" value="george" required /> George</label>
</div>
<div class="myradio">
- <label for="id_beatles_3"><input id="id_beatles_3" name="beatles" type="radio" value="ringo" /> Ringo</label>
+ <label for="id_beatles_3"><input id="id_beatles_3" name="beatles" type="radio" value="ringo" required /> Ringo</label>
</div>
That included the ``<label>`` tags. To get more granular, you can use each
@@ -658,22 +658,22 @@ Selector and checkbox widgets
<label for="id_beatles_0">
John
- <span class="radio"><input id="id_beatles_0" name="beatles" type="radio" value="john" /></span>
+ <span class="radio"><input id="id_beatles_0" name="beatles" type="radio" value="john" required /></span>
</label>
<label for="id_beatles_1">
Paul
- <span class="radio"><input id="id_beatles_1" name="beatles" type="radio" value="paul" /></span>
+ <span class="radio"><input id="id_beatles_1" name="beatles" type="radio" value="paul" required /></span>
</label>
<label for="id_beatles_2">
George
- <span class="radio"><input id="id_beatles_2" name="beatles" type="radio" value="george" /></span>
+ <span class="radio"><input id="id_beatles_2" name="beatles" type="radio" value="george" required /></span>
</label>
<label for="id_beatles_3">
Ringo
- <span class="radio"><input id="id_beatles_3" name="beatles" type="radio" value="ringo" /></span>
+ <span class="radio"><input id="id_beatles_3" name="beatles" type="radio" value="ringo" required /></span>
</label>
If you decide not to loop over the radio buttons -- e.g., if your template
diff --git a/docs/releases/1.10.txt b/docs/releases/1.10.txt
index 05f3c20b1a..a3928188b0 100644
--- a/docs/releases/1.10.txt
+++ b/docs/releases/1.10.txt
@@ -259,6 +259,12 @@ Forms
* The ``<input>`` tag rendered by :class:`~django.forms.CharField` now includes
a ``minlength`` attribute if the field has a ``min_length``.
+* Required form fields now have the ``required`` HTML attribute. Set the new
+ :attr:`Form.use_required_attribute <django.forms.Form.use_required_attribute>`
+ attribute to ``False`` to disable it. The ``required`` attribute isn't
+ included on forms of formsets because the browser validation may not be
+ correct when adding and deleting formsets.
+
Generic Views
~~~~~~~~~~~~~
@@ -760,6 +766,11 @@ Miscellaneous
:attr:`ModelAdmin.save_as_continue
<django.contrib.admin.ModelAdmin.save_as_continue>` attribute to ``False``.
+* Required form fields now have the ``required`` HTML attribute. Set the
+ :attr:`Form.use_required_attribute <django.forms.Form.use_required_attribute>`
+ attribute to ``False`` to disable it. You could also add the ``novalidate``
+ attribute to ``<form>`` if you don't want browser validation.
+
.. _deprecated-features-1.10:
Features deprecated in 1.10
diff --git a/docs/topics/forms/formsets.txt b/docs/topics/forms/formsets.txt
index 8aa3f67b2a..6a0a43b7c1 100644
--- a/docs/topics/forms/formsets.txt
+++ b/docs/topics/forms/formsets.txt
@@ -164,6 +164,11 @@ As we can see, ``formset.errors`` is a list whose entries correspond to the
forms in the formset. Validation was performed for each of the two forms, and
the expected error message appears for the second item.
+Just like when using a normal ``Form``, each form in the formset may include
+HTML attributes such as ``maxlength`` for browser validation. However, forms of
+formsets won't include the ``required`` attribute as that validation may be
+incorrect when adding and deleting forms.
+
.. method:: BaseFormSet.total_error_count()
To check how many errors there are in the formset, we can use the
diff --git a/docs/topics/forms/index.txt b/docs/topics/forms/index.txt
index 487f8dd64e..86de7d1b06 100644
--- a/docs/topics/forms/index.txt
+++ b/docs/topics/forms/index.txt
@@ -259,7 +259,7 @@ The whole form, when rendered for the first time, will look like:
.. code-block:: html+django
<label for="your_name">Your name: </label>
- <input id="your_name" type="text" name="your_name" maxlength="100">
+ <input id="your_name" type="text" name="your_name" maxlength="100" required />
Note that it **does not** include the ``<form>`` tags, or a submit button.
We'll have to provide those ourselves in the template.
@@ -512,11 +512,11 @@ Here's the output of ``{{ form.as_p }}`` for our ``ContactForm`` instance:
.. code-block:: html+django
<p><label for="id_subject">Subject:</label>
- <input id="id_subject" type="text" name="subject" maxlength="100" /></p>
+ <input id="id_subject" type="text" name="subject" maxlength="100" required /></p>
<p><label for="id_message">Message:</label>
- <textarea name="message" id="id_message"></textarea></p>
+ <textarea name="message" id="id_message" required></textarea></p>
<p><label for="id_sender">Sender:</label>
- <input type="email" name="sender" id="id_sender" /></p>
+ <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>
diff --git a/tests/admin_views/tests.py b/tests/admin_views/tests.py
index 5c0d5ed51c..b657afe859 100644
--- a/tests/admin_views/tests.py
+++ b/tests/admin_views/tests.py
@@ -3291,7 +3291,7 @@ class AdminActionsTest(TestCase):
Refs #15964.
"""
response = self.client.get(reverse('admin:admin_views_externalsubscriber_changelist'))
- self.assertContains(response, '''<label>Action: <select name="action">
+ self.assertContains(response, '''<label>Action: <select name="action" required>
<option value="" selected="selected">---------</option>
<option value="delete_selected">Delete selected external
subscribers</option>
diff --git a/tests/forms_tests/field_tests/test_charfield.py b/tests/forms_tests/field_tests/test_charfield.py
index 0927370af3..906b91bc75 100644
--- a/tests/forms_tests/field_tests/test_charfield.py
+++ b/tests/forms_tests/field_tests/test_charfield.py
@@ -119,4 +119,4 @@ class CharFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
def test_charfield_disabled(self):
f = CharField(disabled=True)
- self.assertWidgetRendersTo(f, '<input type="text" name="f" id="id_f" disabled />')
+ self.assertWidgetRendersTo(f, '<input type="text" name="f" id="id_f" disabled required />')
diff --git a/tests/forms_tests/field_tests/test_choicefield.py b/tests/forms_tests/field_tests/test_choicefield.py
index 013766d50b..69b4d9e342 100644
--- a/tests/forms_tests/field_tests/test_choicefield.py
+++ b/tests/forms_tests/field_tests/test_choicefield.py
@@ -81,6 +81,6 @@ class ChoiceFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
f = ChoiceField(choices=[('J', 'John'), ('P', 'Paul')], disabled=True)
self.assertWidgetRendersTo(
f,
- '<select id="id_f" name="f" disabled><option value="J">John</option>'
+ '<select id="id_f" name="f" disabled required><option value="J">John</option>'
'<option value="P">Paul</option></select>'
)
diff --git a/tests/forms_tests/field_tests/test_decimalfield.py b/tests/forms_tests/field_tests/test_decimalfield.py
index 3b23ced714..02600bcb5b 100644
--- a/tests/forms_tests/field_tests/test_decimalfield.py
+++ b/tests/forms_tests/field_tests/test_decimalfield.py
@@ -14,7 +14,7 @@ class DecimalFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
def test_decimalfield_1(self):
f = DecimalField(max_digits=4, decimal_places=2)
- self.assertWidgetRendersTo(f, '<input id="id_f" step="0.01" type="number" name="f" />')
+ self.assertWidgetRendersTo(f, '<input id="id_f" step="0.01" type="number" name="f" required />')
with self.assertRaisesMessage(ValidationError, "'This field is required.'"):
f.clean('')
with self.assertRaisesMessage(ValidationError, "'This field is required.'"):
@@ -80,7 +80,10 @@ class DecimalFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
max_value=decimal.Decimal('1.5'),
min_value=decimal.Decimal('0.5')
)
- self.assertWidgetRendersTo(f, '<input step="0.01" name="f" min="0.5" max="1.5" type="number" id="id_f" />')
+ self.assertWidgetRendersTo(
+ f,
+ '<input step="0.01" name="f" min="0.5" max="1.5" type="number" id="id_f" required />',
+ )
with self.assertRaisesMessage(ValidationError, "'Ensure this value is less than or equal to 1.5.'"):
f.clean('1.6')
with self.assertRaisesMessage(ValidationError, "'Ensure this value is greater than or equal to 0.5.'"):
@@ -136,7 +139,7 @@ class DecimalFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
f = DecimalField(max_digits=20)
self.assertEqual(f.widget_attrs(NumberInput()), {'step': 'any'})
f = DecimalField(max_digits=6, widget=NumberInput(attrs={'step': '0.01'}))
- self.assertWidgetRendersTo(f, '<input step="0.01" name="f" type="number" id="id_f" />')
+ self.assertWidgetRendersTo(f, '<input step="0.01" name="f" type="number" id="id_f" required />')
def test_decimalfield_localized(self):
"""
@@ -144,7 +147,7 @@ class DecimalFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
number input specific attributes.
"""
f = DecimalField(localize=True)
- self.assertWidgetRendersTo(f, '<input id="id_f" name="f" type="text" />')
+ self.assertWidgetRendersTo(f, '<input id="id_f" name="f" type="text" required />')
def test_decimalfield_changed(self):
f = DecimalField(max_digits=2, decimal_places=2)
diff --git a/tests/forms_tests/field_tests/test_durationfield.py b/tests/forms_tests/field_tests/test_durationfield.py
index 800d5d6ae3..28fd245a79 100644
--- a/tests/forms_tests/field_tests/test_durationfield.py
+++ b/tests/forms_tests/field_tests/test_durationfield.py
@@ -24,7 +24,7 @@ class DurationFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
def test_durationfield_render(self):
self.assertWidgetRendersTo(
DurationField(initial=datetime.timedelta(hours=1)),
- '<input id="id_f" type="text" name="f" value="01:00:00">',
+ '<input id="id_f" type="text" name="f" value="01:00:00" required>',
)
def test_durationfield_integer_value(self):
diff --git a/tests/forms_tests/field_tests/test_emailfield.py b/tests/forms_tests/field_tests/test_emailfield.py
index d9fe64d3bb..4d37a7dc00 100644
--- a/tests/forms_tests/field_tests/test_emailfield.py
+++ b/tests/forms_tests/field_tests/test_emailfield.py
@@ -11,7 +11,7 @@ class EmailFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
def test_emailfield_1(self):
f = EmailField()
- self.assertWidgetRendersTo(f, '<input type="email" name="f" id="id_f" />')
+ self.assertWidgetRendersTo(f, '<input type="email" name="f" id="id_f" required />')
with self.assertRaisesMessage(ValidationError, "'This field is required.'"):
f.clean('')
with self.assertRaisesMessage(ValidationError, "'This field is required.'"):
@@ -42,7 +42,10 @@ class EmailFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
def test_emailfield_min_max_length(self):
f = EmailField(min_length=10, max_length=15)
- self.assertWidgetRendersTo(f, '<input id="id_f" type="email" name="f" maxlength="15" minlength="10" />')
+ self.assertWidgetRendersTo(
+ f,
+ '<input id="id_f" type="email" name="f" maxlength="15" minlength="10" required />',
+ )
with self.assertRaisesMessage(ValidationError, "'Ensure this value has at least 10 characters (it has 9).'"):
f.clean('a@foo.com')
self.assertEqual('alf@foo.com', f.clean('alf@foo.com'))
diff --git a/tests/forms_tests/field_tests/test_floatfield.py b/tests/forms_tests/field_tests/test_floatfield.py
index 5ae799d24b..d4ef4f496b 100644
--- a/tests/forms_tests/field_tests/test_floatfield.py
+++ b/tests/forms_tests/field_tests/test_floatfield.py
@@ -11,7 +11,7 @@ class FloatFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
def test_floatfield_1(self):
f = FloatField()
- self.assertWidgetRendersTo(f, '<input step="any" type="number" name="f" id="id_f" />')
+ self.assertWidgetRendersTo(f, '<input step="any" type="number" name="f" id="id_f" required />')
with self.assertRaisesMessage(ValidationError, "'This field is required.'"):
f.clean('')
with self.assertRaisesMessage(ValidationError, "'This field is required.'"):
@@ -48,7 +48,10 @@ class FloatFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
def test_floatfield_3(self):
f = FloatField(max_value=1.5, min_value=0.5)
- self.assertWidgetRendersTo(f, '<input step="any" name="f" min="0.5" max="1.5" type="number" id="id_f" />')
+ self.assertWidgetRendersTo(
+ f,
+ '<input step="any" name="f" min="0.5" max="1.5" type="number" id="id_f" required />',
+ )
with self.assertRaisesMessage(ValidationError, "'Ensure this value is less than or equal to 1.5.'"):
f.clean('1.6')
with self.assertRaisesMessage(ValidationError, "'Ensure this value is greater than or equal to 0.5.'"):
@@ -60,7 +63,10 @@ class FloatFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
def test_floatfield_widget_attrs(self):
f = FloatField(widget=NumberInput(attrs={'step': 0.01, 'max': 1.0, 'min': 0.0}))
- self.assertWidgetRendersTo(f, '<input step="0.01" name="f" min="0.0" max="1.0" type="number" id="id_f" />')
+ self.assertWidgetRendersTo(
+ f,
+ '<input step="0.01" name="f" min="0.0" max="1.0" type="number" id="id_f" required />',
+ )
def test_floatfield_localized(self):
"""
@@ -68,7 +74,7 @@ class FloatFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
number input specific attributes.
"""
f = FloatField(localize=True)
- self.assertWidgetRendersTo(f, '<input id="id_f" name="f" type="text" />')
+ self.assertWidgetRendersTo(f, '<input id="id_f" name="f" type="text" required />')
def test_floatfield_changed(self):
f = FloatField()
diff --git a/tests/forms_tests/field_tests/test_integerfield.py b/tests/forms_tests/field_tests/test_integerfield.py
index 15bbca1ee8..d5c14857ed 100644
--- a/tests/forms_tests/field_tests/test_integerfield.py
+++ b/tests/forms_tests/field_tests/test_integerfield.py
@@ -11,7 +11,7 @@ class IntegerFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
def test_integerfield_1(self):
f = IntegerField()
- self.assertWidgetRendersTo(f, '<input type="number" name="f" id="id_f" />')
+ self.assertWidgetRendersTo(f, '<input type="number" name="f" id="id_f" required />')
with self.assertRaisesMessage(ValidationError, "'This field is required.'"):
f.clean('')
with self.assertRaisesMessage(ValidationError, "'This field is required.'"):
@@ -53,7 +53,7 @@ class IntegerFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
def test_integerfield_3(self):
f = IntegerField(max_value=10)
- self.assertWidgetRendersTo(f, '<input max="10" type="number" name="f" id="id_f" />')
+ self.assertWidgetRendersTo(f, '<input max="10" type="number" name="f" id="id_f" required />')
with self.assertRaisesMessage(ValidationError, "'This field is required.'"):
f.clean(None)
self.assertEqual(1, f.clean(1))
@@ -68,7 +68,7 @@ class IntegerFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
def test_integerfield_4(self):
f = IntegerField(min_value=10)
- self.assertWidgetRendersTo(f, '<input id="id_f" type="number" name="f" min="10" />')
+ self.assertWidgetRendersTo(f, '<input id="id_f" type="number" name="f" min="10" required />')
with self.assertRaisesMessage(ValidationError, "'This field is required.'"):
f.clean(None)
with self.assertRaisesMessage(ValidationError, "'Ensure this value is greater than or equal to 10.'"):
@@ -82,7 +82,7 @@ class IntegerFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
def test_integerfield_5(self):
f = IntegerField(min_value=10, max_value=20)
- self.assertWidgetRendersTo(f, '<input id="id_f" max="20" type="number" name="f" min="10" />')
+ self.assertWidgetRendersTo(f, '<input id="id_f" max="20" type="number" name="f" min="10" required />')
with self.assertRaisesMessage(ValidationError, "'This field is required.'"):
f.clean(None)
with self.assertRaisesMessage(ValidationError, "'Ensure this value is greater than or equal to 10.'"):
@@ -103,7 +103,7 @@ class IntegerFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
number input specific attributes.
"""
f1 = IntegerField(localize=True)
- self.assertWidgetRendersTo(f1, '<input id="id_f" name="f" type="text" />')
+ self.assertWidgetRendersTo(f1, '<input id="id_f" name="f" type="text" required />')
def test_integerfield_float(self):
f = IntegerField()
diff --git a/tests/forms_tests/field_tests/test_multivaluefield.py b/tests/forms_tests/field_tests/test_multivaluefield.py
index 79a3425155..7703371d59 100644
--- a/tests/forms_tests/field_tests/test_multivaluefield.py
+++ b/tests/forms_tests/field_tests/test_multivaluefield.py
@@ -112,15 +112,15 @@ class MultiValueFieldTest(SimpleTestCase):
form.as_table(),
"""
<tr><th><label for="id_field1_0">Field1:</label></th>
- <td><input type="text" name="field1_0" id="id_field1_0" />
- <select multiple="multiple" name="field1_1" id="id_field1_1">
+ <td><input type="text" name="field1_0" id="id_field1_0" required />
+ <select multiple="multiple" name="field1_1" id="id_field1_1" required>
<option value="J">John</option>
<option value="P">Paul</option>
<option value="G">George</option>
<option value="R">Ringo</option>
</select>
- <input type="text" name="field1_2_0" id="id_field1_2_0" />
- <input type="text" name="field1_2_1" id="id_field1_2_1" /></td></tr>
+ <input type="text" name="field1_2_0" id="id_field1_2_0" required />
+ <input type="text" name="field1_2_1" id="id_field1_2_1" required /></td></tr>
""",
)
@@ -135,15 +135,15 @@ class MultiValueFieldTest(SimpleTestCase):
form.as_table(),
"""
<tr><th><label for="id_field1_0">Field1:</label></th>
- <td><input type="text" name="field1_0" value="some text" id="id_field1_0" />
- <select multiple="multiple" name="field1_1" id="id_field1_1">
+ <td><input type="text" name="field1_0" value="some text" id="id_field1_0" required />
+ <select multiple="multiple" name="field1_1" id="id_field1_1" required>
<option value="J" selected="selected">John</option>
<option value="P" selected="selected">Paul</option>
<option value="G">George</option>
<option value="R">Ringo</option>
</select>
- <input type="text" name="field1_2_0" value="2007-04-25" id="id_field1_2_0" />
- <input type="text" name="field1_2_1" value="06:24:00" id="id_field1_2_1" /></td></tr>
+ <input type="text" name="field1_2_0" value="2007-04-25" id="id_field1_2_0" required />
+ <input type="text" name="field1_2_1" value="06:24:00" id="id_field1_2_1" required /></td></tr>
""",
)
diff --git a/tests/forms_tests/field_tests/test_urlfield.py b/tests/forms_tests/field_tests/test_urlfield.py
index 0ad1bb65f9..24da712717 100644
--- a/tests/forms_tests/field_tests/test_urlfield.py
+++ b/tests/forms_tests/field_tests/test_urlfield.py
@@ -11,7 +11,7 @@ class URLFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
def test_urlfield_1(self):
f = URLField()
- self.assertWidgetRendersTo(f, '<input type="url" name="f" id="id_f" />')
+ self.assertWidgetRendersTo(f, '<input type="url" name="f" id="id_f" required />')
with self.assertRaisesMessage(ValidationError, "'This field is required.'"):
f.clean('')
with self.assertRaisesMessage(ValidationError, "'This field is required.'"):
@@ -91,7 +91,7 @@ class URLFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
def test_urlfield_5(self):
f = URLField(min_length=15, max_length=20)
- self.assertWidgetRendersTo(f, '<input id="id_f" type="url" name="f" maxlength="20" minlength="15" />')
+ self.assertWidgetRendersTo(f, '<input id="id_f" type="url" name="f" maxlength="20" minlength="15" required />')
with self.assertRaisesMessage(ValidationError, "'Ensure this value has at least 15 characters (it has 12).'"):
f.clean('http://f.com')
self.assertEqual('http://example.com', f.clean('http://example.com'))
diff --git a/tests/forms_tests/tests/test_forms.py b/tests/forms_tests/tests/test_forms.py
index a5d8fbebdb..4309fb3d86 100644
--- a/tests/forms_tests/tests/test_forms.py
+++ b/tests/forms_tests/tests/test_forms.py
@@ -60,15 +60,15 @@ class FormsTestCase(SimpleTestCase):
self.assertEqual(p.cleaned_data["birthday"], datetime.date(1940, 10, 9))
self.assertHTMLEqual(
str(p['first_name']),
- '<input type="text" name="first_name" value="John" id="id_first_name" />'
+ '<input type="text" name="first_name" value="John" id="id_first_name" required />'
)
self.assertHTMLEqual(
str(p['last_name']),
- '<input type="text" name="last_name" value="Lennon" id="id_last_name" />'
+ '<input type="text" name="last_name" value="Lennon" id="id_last_name" required />'
)
self.assertHTMLEqual(
str(p['birthday']),
- '<input type="text" name="birthday" value="1940-10-9" id="id_birthday" />'
+ '<input type="text" name="birthday" value="1940-10-9" id="id_birthday" required />'
)
msg = "Key 'nonexistentfield' not found in 'Person'. Choices are: birthday, first_name, last_name."
@@ -82,9 +82,9 @@ class FormsTestCase(SimpleTestCase):
self.assertHTMLEqual(
'\n'.join(form_output),
- """<input type="text" name="first_name" value="John" id="id_first_name" />
-<input type="text" name="last_name" value="Lennon" id="id_last_name" />
-<input type="text" name="birthday" value="1940-10-9" id="id_birthday" />"""
+ """<input type="text" name="first_name" value="John" id="id_first_name" required />
+<input type="text" name="last_name" value="Lennon" id="id_last_name" required />
+<input type="text" name="birthday" value="1940-10-9" id="id_birthday" required />"""
)
form_output = []
@@ -100,11 +100,11 @@ class FormsTestCase(SimpleTestCase):
self.assertHTMLEqual(
str(p),
"""<tr><th><label for="id_first_name">First name:</label></th><td>
-<input type="text" name="first_name" value="John" id="id_first_name" /></td></tr>
+<input type="text" name="first_name" value="John" id="id_first_name" required /></td></tr>
<tr><th><label for="id_last_name">Last name:</label></th><td>
-<input type="text" name="last_name" value="Lennon" id="id_last_name" /></td></tr>
+<input type="text" name="last_name" value="Lennon" id="id_last_name" required /></td></tr>
<tr><th><label for="id_birthday">Birthday:</label></th><td>
-<input type="text" name="birthday" value="1940-10-9" id="id_birthday" /></td></tr>"""
+<input type="text" name="birthday" value="1940-10-9" id="id_birthday" required /></td></tr>"""
)
def test_empty_dict(self):
@@ -120,49 +120,49 @@ class FormsTestCase(SimpleTestCase):
str(p),
"""<tr><th><label for="id_first_name">First name:</label></th><td>
<ul class="errorlist"><li>This field is required.</li></ul>
-<input type="text" name="first_name" id="id_first_name" /></td></tr>
+<input type="text" name="first_name" id="id_first_name" required /></td></tr>
<tr><th><label for="id_last_name">Last name:</label></th>
<td><ul class="errorlist"><li>This field is required.</li></ul>
-<input type="text" name="last_name" id="id_last_name" /></td></tr>
+<input type="text" name="last_name" id="id_last_name" required /></td></tr>
<tr><th><label for="id_birthday">Birthday:</label></th><td>
<ul class="errorlist"><li>This field is required.</li></ul>
-<input type="text" name="birthday" id="id_birthday" /></td></tr>"""
+<input type="text" name="birthday" id="id_birthday" required /></td></tr>"""
)
self.assertHTMLEqual(
p.as_table(),
"""<tr><th><label for="id_first_name">First name:</label></th><td>
<ul class="errorlist"><li>This field is required.</li></ul>
-<input type="text" name="first_name" id="id_first_name" /></td></tr>
+<input type="text" name="first_name" id="id_first_name" required /></td></tr>
<tr><th><label for="id_last_name">Last name:</label></th>
<td><ul class="errorlist"><li>This field is required.</li></ul>
-<input type="text" name="last_name" id="id_last_name" /></td></tr>
+<input type="text" name="last_name" id="id_last_name" required /></td></tr>
<tr><th><label for="id_birthday">Birthday:</label></th>
<td><ul class="errorlist"><li>This field is required.</li></ul>
-<input type="text" name="birthday" id="id_birthday" /></td></tr>"""
+<input type="text" name="birthday" id="id_birthday" required /></td></tr>"""
)
self.assertHTMLEqual(
p.as_ul(),
"""<li><ul class="errorlist"><li>This field is required.</li></ul>
<label for="id_first_name">First name:</label>
-<input type="text" name="first_name" id="id_first_name" /></li>
+<input type="text" name="first_name" id="id_first_name" required /></li>
<li><ul class="errorlist"><li>This field is required.</li></ul>
<label for="id_last_name">Last name:</label>
-<input type="text" name="last_name" id="id_last_name" /></li>
+<input type="text" name="last_name" id="id_last_name" required /></li>
<li><ul class="errorlist"><li>This field is required.</li></ul>
<label for="id_birthday">Birthday:</label>
-<input type="text" name="birthday" id="id_birthday" /></li>"""
+<input type="text" name="birthday" id="id_birthday" required /></li>"""
)
self.assertHTMLEqual(
p.as_p(),
"""<ul class="errorlist"><li>This field is required.</li></ul>
<p><label for="id_first_name">First name:</label>
-<input type="text" name="first_name" id="id_first_name" /></p>
+<input type="text" name="first_name" id="id_first_name" required /></p>
<ul class="errorlist"><li>This field is required.</li></ul>
<p><label for="id_last_name">Last name:</label>
-<input type="text" name="last_name" id="id_last_name" /></p>
+<input type="text" name="last_name" id="id_last_name" required /></p>
<ul class="errorlist"><li>This field is required.</li></ul>
<p><label for="id_birthday">Birthday:</label>
-<input type="text" name="birthday" id="id_birthday" /></p>"""
+<input type="text" name="birthday" id="id_birthday" required /></p>"""
)
def test_unbound_form(self):
@@ -181,38 +181,38 @@ class FormsTestCase(SimpleTestCase):
self.assertHTMLEqual(
str(p),
"""<tr><th><label for="id_first_name">First name:</label></th><td>
-<input type="text" name="first_name" id="id_first_name" /></td></tr>
+<input type="text" name="first_name" id="id_first_name" required /></td></tr>
<tr><th><label for="id_last_name">Last name:</label></th><td>
-<input type="text" name="last_name" id="id_last_name" /></td></tr>
+<input type="text" name="last_name" id="id_last_name" required /></td></tr>
<tr><th><label for="id_birthday">Birthday:</label></th><td>
-<input type="text" name="birthday" id="id_birthday" /></td></tr>"""
+<input type="text" name="birthday" id="id_birthday" required /></td></tr>"""
)
self.assertHTMLEqual(
p.as_table(),
"""<tr><th><label for="id_first_name">First name:</label></th><td>
-<input type="text" name="first_name" id="id_first_name" /></td></tr>
+<input type="text" name="first_name" id="id_first_name" required /></td></tr>
<tr><th><label for="id_last_name">Last name:</label></th><td>
-<input type="text" name="last_name" id="id_last_name" /></td></tr>
+<input type="text" name="last_name" id="id_last_name" required /></td></tr>
<tr><th><label for="id_birthday">Birthday:</label></th><td>
-<input type="text" name="birthday" id="id_birthday" /></td></tr>"""
+<input type="text" name="birthday" id="id_birthday" required /></td></tr>"""
)
self.assertHTMLEqual(
p.as_ul(),
"""<li><label for="id_first_name">First name:</label>
-<input type="text" name="first_name" id="id_first_name" /></li>
+<input type="text" name="first_name" id="id_first_name" required /></li>
<li><label for="id_last_name">Last name:</label>
-<input type="text" name="last_name" id="id_last_name" /></li>
+<input type="text" name="last_name" id="id_last_name" required /></li>
<li><label for="id_birthday">Birthday:</label>
-<input type="text" name="birthday" id="id_birthday" /></li>"""
+<input type="text" name="birthday" id="id_birthday" required /></li>"""
)
self.assertHTMLEqual(
p.as_p(),
"""<p><label for="id_first_name">First name:</label>
-<input type="text" name="first_name" id="id_first_name" /></p>
+<input type="text" name="first_name" id="id_first_name" required /></p>
<p><label for="id_last_name">Last name:</label>
-<input type="text" name="last_name" id="id_last_name" /></p>
+<input type="text" name="last_name" id="id_last_name" required /></p>
<p><label for="id_birthday">Birthday:</label>
-<input type="text" name="birthday" id="id_birthday" /></p>"""
+<input type="text" name="birthday" id="id_birthday" required /></p>"""
)
def test_unicode_values(self):
@@ -225,33 +225,33 @@ class FormsTestCase(SimpleTestCase):
self.assertHTMLEqual(
p.as_table(),
'<tr><th><label for="id_first_name">First name:</label></th><td>'
- '<input type="text" name="first_name" value="John" id="id_first_name" /></td></tr>\n'
+ '<input type="text" name="first_name" value="John" id="id_first_name" required /></td></tr>\n'
'<tr><th><label for="id_last_name">Last name:</label>'
'</th><td><input type="text" name="last_name" '
'value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111"'
- 'id="id_last_name" /></td></tr>\n'
+ 'id="id_last_name" required /></td></tr>\n'
'<tr><th><label for="id_birthday">Birthday:</label></th><td>'
- '<input type="text" name="birthday" value="1940-10-9" id="id_birthday" /></td></tr>'
+ '<input type="text" name="birthday" value="1940-10-9" id="id_birthday" required /></td></tr>'
)
self.assertHTMLEqual(
p.as_ul(),
'<li><label for="id_first_name">First name:</label> '
- '<input type="text" name="first_name" value="John" id="id_first_name" /></li>\n'
+ '<input type="text" name="first_name" value="John" id="id_first_name" required /></li>\n'
'<li><label for="id_last_name">Last name:</label> '
'<input type="text" name="last_name" '
- 'value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" id="id_last_name" /></li>\n'
+ 'value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" id="id_last_name" required /></li>\n'
'<li><label for="id_birthday">Birthday:</label> '
- '<input type="text" name="birthday" value="1940-10-9" id="id_birthday" /></li>'
+ '<input type="text" name="birthday" value="1940-10-9" id="id_birthday" required /></li>'
)
self.assertHTMLEqual(
p.as_p(),
'<p><label for="id_first_name">First name:</label> '
- '<input type="text" name="first_name" value="John" id="id_first_name" /></p>\n'
+ '<input type="text" name="first_name" value="John" id="id_first_name" required /></p>\n'
'<p><label for="id_last_name">Last name:</label> '
'<input type="text" name="last_name" '
- 'value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" id="id_last_name" /></p>\n'
+ 'value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" id="id_last_name" required /></p>\n'
'<p><label for="id_birthday">Birthday:</label> '
- '<input type="text" name="birthday" value="1940-10-9" id="id_birthday" /></p>'
+ '<input type="text" name="birthday" value="1940-10-9" id="id_birthday" required /></p>'
)
p = Person({'last_name': 'Lennon'})
@@ -271,9 +271,12 @@ class FormsTestCase(SimpleTestCase):
self.assertEqual(p['first_name'].errors.as_text(), '* This field is required.')
p = Person()
- self.assertHTMLEqual(str(p['first_name']), '<input type="text" name="first_name" id="id_first_name" />')
- self.assertHTMLEqual(str(p['last_name']), '<input type="text" name="last_name" id="id_last_name" />')
- self.assertHTMLEqual(str(p['birthday']), '<input type="text" name="birthday" id="id_birthday" />')
+ self.assertHTMLEqual(
+ str(p['first_name']),
+ '<input type="text" name="first_name" id="id_first_name" required />',
+ )
+ self.assertHTMLEqual(str(p['last_name']), '<input type="text" name="last_name" id="id_last_name" required />')
+ self.assertHTMLEqual(str(p['birthday']), '<input type="text" name="birthday" id="id_birthday" required />')
def test_cleaned_data_only_fields(self):
# cleaned_data will always *only* contain a key for fields defined in the
@@ -333,29 +336,29 @@ class FormsTestCase(SimpleTestCase):
self.assertHTMLEqual(
p.as_table(),
"""<tr><th><label for="first_name_id">First name:</label></th><td>
-<input type="text" name="first_name" id="first_name_id" /></td></tr>
+<input type="text" name="first_name" id="first_name_id" required /></td></tr>
<tr><th><label for="last_name_id">Last name:</label></th><td>
-<input type="text" name="last_name" id="last_name_id" /></td></tr>
+<input type="text" name="last_name" id="last_name_id" required /></td></tr>
<tr><th><label for="birthday_id">Birthday:</label></th><td>
-<input type="text" name="birthday" id="birthday_id" /></td></tr>"""
+<input type="text" name="birthday" id="birthday_id" required /></td></tr>"""
)
self.assertHTMLEqual(
p.as_ul(),
"""<li><label for="first_name_id">First name:</label>
-<input type="text" name="first_name" id="first_name_id" /></li>
+<input type="text" name="first_name" id="first_name_id" required /></li>
<li><label for="last_name_id">Last name:</label>
-<input type="text" name="last_name" id="last_name_id" /></li>
+<input type="text" name="last_name" id="last_name_id" required /></li>
<li><label for="birthday_id">Birthday:</label>
-<input type="text" name="birthday" id="birthday_id" /></li>"""
+<input type="text" name="birthday" id="birthday_id" required /></li>"""
)
self.assertHTMLEqual(
p.as_p(),
"""<p><label for="first_name_id">First name:</label>
-<input type="text" name="first_name" id="first_name_id" /></p>
+<input type="text" name="first_name" id="first_name_id" required /></p>
<p><label for="last_name_id">Last name:</label>
-<input type="text" name="last_name" id="last_name_id" /></p>
+<input type="text" name="last_name" id="last_name_id" required /></p>
<p><label for="birthday_id">Birthday:</label>
-<input type="text" name="birthday" id="birthday_id" /></p>"""
+<input type="text" name="birthday" id="birthday_id" required /></p>"""
)
def test_auto_id_true(self):
@@ -365,11 +368,11 @@ class FormsTestCase(SimpleTestCase):
self.assertHTMLEqual(
p.as_ul(),
"""<li><label for="first_name">First name:</label>
-<input type="text" name="first_name" id="first_name" /></li>
+<input type="text" name="first_name" id="first_name" required /></li>
<li><label for="last_name">Last name:</label>
-<input type="text" name="last_name" id="last_name" /></li>
+<input type="text" name="last_name" id="last_name" required /></li>
<li><label for="birthday">Birthday:</label>
-<input type="text" name="birthday" id="birthday" /></li>"""
+<input type="text" name="birthday" id="birthday" required /></li>"""
)
def test_auto_id_false(self):
@@ -378,9 +381,9 @@ class FormsTestCase(SimpleTestCase):
p = Person(auto_id=False)
self.assertHTMLEqual(
p.as_ul(),
- """<li>First name: <input type="text" name="first_name" /></li>
-<li>Last name: <input type="text" name="last_name" /></li>
-<li>Birthday: <input type="text" name="birthday" /></li>"""
+ """<li>First name: <input type="text" name="first_name" required /></li>
+<li>Last name: <input type="text" name="last_name" required /></li>
+<li>Birthday: <input type="text" name="birthday" required /></li>"""
)
def test_id_on_field(self):
@@ -390,9 +393,9 @@ class FormsTestCase(SimpleTestCase):
self.assertHTMLEqual(
p.as_ul(),
"""<li><label for="first_name_id">First name:</label>
-<input type="text" id="first_name_id" name="first_name" /></li>
-<li>Last name: <input type="text" name="last_name" /></li>
-<li>Birthday: <input type="text" name="birthday" /></li>"""
+<input type="text" id="first_name_id" name="first_name" required /></li>
+<li>Last name: <input type="text" name="last_name" required /></li>
+<li>Birthday: <input type="text" name="birthday" required /></li>"""
)
def test_auto_id_on_form_and_field(self):
@@ -402,11 +405,11 @@ class FormsTestCase(SimpleTestCase):
self.assertHTMLEqual(
p.as_ul(),
"""<li><label for="first_name_id">First name:</label>
-<input type="text" id="first_name_id" name="first_name" /></li>
+<input type="text" id="first_name_id" name="first_name" required /></li>
<li><label for="last_name">Last name:</label>
-<input type="text" name="last_name" id="last_name" /></li>
+<input type="text" name="last_name" id="last_name" required /></li>
<li><label for="birthday">Birthday:</label>
-<input type="text" name="birthday" id="birthday" /></li>"""
+<input type="text" name="birthday" id="birthday" required /></li>"""
)
def test_various_boolean_values(self):
@@ -415,26 +418,33 @@ class FormsTestCase(SimpleTestCase):
get_spam = BooleanField()
f = SignupForm(auto_id=False)
- self.assertHTMLEqual(str(f['email']), '<input type="email" name="email" />')
- self.assertHTMLEqual(str(f['get_spam']), '<input type="checkbox" name="get_spam" />')
+ self.assertHTMLEqual(str(f['email']), '<input type="email" name="email" required />')
+ self.assertHTMLEqual(str(f['get_spam']), '<input type="checkbox" name="get_spam" required />')
f = SignupForm({'email': 'test@example.com', 'get_spam': True}, auto_id=False)
- self.assertHTMLEqual(str(f['email']), '<input type="email" name="email" value="test@example.com" />')
- self.assertHTMLEqual(str(f['get_spam']), '<input checked="checked" type="checkbox" name="get_spam" />')
+ self.assertHTMLEqual(str(f['email']), '<input type="email" name="email" value="test@example.com" required />')
+ self.assertHTMLEqual(
+ str(f['get_spam']),
+ '<input checked="checked" type="checkbox" name="get_spam" required />',
+ )
# 'True' or 'true' should be rendered without a value attribute
f = SignupForm({'email': 'test@example.com', 'get_spam': 'True'}, auto_id=False)
- self.assertHTMLEqual(str(f['get_spam']), '<input checked="checked" type="checkbox" name="get_spam" />')
+ self.assertHTMLEqual(
+ str(f['get_spam']),
+ '<input checked="checked" type="checkbox" name="get_spam" required />',
+ )
f = SignupForm({'email': 'test@example.com', 'get_spam': 'true'}, auto_id=False)
- self.assertHTMLEqual(str(f['get_spam']), '<input checked="checked" type="checkbox" name="get_spam" />')
+ self.assertHTMLEqual(
+ str(f['get_spam']), '<input checked="checked" type="checkbox" name="get_spam" required />')
# A value of 'False' or 'false' should be rendered unchecked
f = SignupForm({'email': 'test@example.com', 'get_spam': 'False'}, auto_id=False)
- self.assertHTMLEqual(str(f['get_spam']), '<input type="checkbox" name="get_spam" />')
+ self.assertHTMLEqual(str(f['get_spam']), '<input type="checkbox" name="get_spam" required />')
f = SignupForm({'email': 'test@example.com', 'get_spam': 'false'}, auto_id=False)
- self.assertHTMLEqual(str(f['get_spam']), '<input type="checkbox" name="get_spam" />')
+ self.assertHTMLEqual(str(f['get_spam']), '<input type="checkbox" name="get_spam" required />')
# A value of '0' should be interpreted as a True value (#16820)
f = SignupForm({'email': 'test@example.com', 'get_spam': '0'})
@@ -448,13 +458,16 @@ class FormsTestCase(SimpleTestCase):
message = CharField(widget=Textarea)
f = ContactForm(auto_id=False)
- self.assertHTMLEqual(str(f['subject']), '<input type="text" name="subject" />')
- self.assertHTMLEqual(str(f['message']), '<textarea name="message" rows="10" cols="40"></textarea>')
+ self.assertHTMLEqual(str(f['subject']), '<input type="text" name="subject" required />')
+ self.assertHTMLEqual(str(f['message']), '<textarea name="message" rows="10" cols="40" required></textarea>')
# as_textarea(), as_text() and as_hidden() are shortcuts for changing the output
# widget type:
- self.assertHTMLEqual(f['subject'].as_textarea(), '<textarea name="subject" rows="10" cols="40"></textarea>')
- self.assertHTMLEqual(f['message'].as_text(), '<input type="text" name="message" />')
+ self.assertHTMLEqual(
+ f['subject'].as_textarea(),
+ '<textarea name="subject" rows="10" cols="40" required></textarea>',
+ )
+ self.assertHTMLEqual(f['message'].as_text(), '<input type="text" name="message" required />')
self.assertHTMLEqual(f['message'].as_hidden(), '<input type="hidden" name="message" />')
# The 'widget' parameter to a Field can also be an instance:
@@ -463,17 +476,20 @@ class FormsTestCase(SimpleTestCase):
message = CharField(widget=Textarea(attrs={'rows': 80, 'cols': 20}))
f = ContactForm(auto_id=False)
- self.assertHTMLEqual(str(f['message']), '<textarea name="message" rows="80" cols="20"></textarea>')
+ self.assertHTMLEqual(str(f['message']), '<textarea name="message" rows="80" cols="20" required></textarea>')
# Instance-level attrs are *not* carried over to as_textarea(), as_text() and
# as_hidden():
- self.assertHTMLEqual(f['message'].as_text(), '<input type="text" name="message" />')
+ self.assertHTMLEqual(f['message'].as_text(), '<input type="text" name="message" required />')
f = ContactForm({'subject': 'Hello', 'message': 'I love you.'}, auto_id=False)
self.assertHTMLEqual(
f['subject'].as_textarea(),
- '<textarea rows="10" cols="40" name="subject">Hello</textarea>'
+ '<textarea rows="10" cols="40" name="subject" required>Hello</textarea>'
+ )
+ self.assertHTMLEqual(
+ f['message'].as_text(),
+ '<input type="text" name="message" value="I love you." required />',
)
- self.assertHTMLEqual(f['message'].as_text(), '<input type="text" name="message" value="I love you." />')
self.assertHTMLEqual(f['message'].as_hidden(), '<input type="hidden" name="message" value="I love you." />')
def test_forms_with_choices(self):
@@ -483,12 +499,12 @@ class FormsTestCase(SimpleTestCase):
language = ChoiceField(choices=[('P', 'Python'), ('J', 'Java')])
f = FrameworkForm(auto_id=False)
- self.assertHTMLEqual(str(f['language']), """<select name="language">
+ self.assertHTMLEqual(str(f['language']), """<select name="language" required>
<option value="P">Python</option>
<option value="J">Java</option>
</select>""")
f = FrameworkForm({'name': 'Django', 'language': 'P'}, auto_id=False)
- self.assertHTMLEqual(str(f['language']), """<select name="language">
+ self.assertHTMLEqual(str(f['language']), """<select name="language" required>
<option value="P" selected="selected">Python</option>
<option value="J">Java</option>
</select>""")
@@ -500,7 +516,7 @@ class FormsTestCase(SimpleTestCase):
language = ChoiceField(choices=[('', '------'), ('P', 'Python'), ('J', 'Java')])
f = FrameworkForm(auto_id=False)
- self.assertHTMLEqual(str(f['language']), """<select name="language">
+ self.assertHTMLEqual(str(f['language']), """<select name="language" required>
<option value="" selected="selected">------</option>
<option value="P">Python</option>
<option value="J">Java</option>
@@ -512,12 +528,12 @@ class FormsTestCase(SimpleTestCase):
language = ChoiceField(choices=[('P', 'Python'), ('J', 'Java')], widget=Select(attrs={'class': 'foo'}))
f = FrameworkForm(auto_id=False)
- self.assertHTMLEqual(str(f['language']), """<select class="foo" name="language">
+ self.assertHTMLEqual(str(f['language']), """<select class="foo" name="language" required>
<option value="P">Python</option>
<option value="J">Java</option>
</select>""")
f = FrameworkForm({'name': 'Django', 'language': 'P'}, auto_id=False)
- self.assertHTMLEqual(str(f['language']), """<select class="foo" name="language">
+ self.assertHTMLEqual(str(f['language']), """<select class="foo" name="language" required>
<option value="P" selected="selected">Python</option>
<option value="J">Java</option>
</select>""")
@@ -533,12 +549,12 @@ class FormsTestCase(SimpleTestCase):
)
f = FrameworkForm(auto_id=False)
- self.assertHTMLEqual(str(f['language']), """<select class="foo" name="language">
+ self.assertHTMLEqual(str(f['language']), """<select class="foo" name="language" required>
<option value="P">Python</option>
<option value="J">Java</option>
</select>""")
f = FrameworkForm({'name': 'Django', 'language': 'P'}, auto_id=False)
- self.assertHTMLEqual(str(f['language']), """<select class="foo" name="language">
+ self.assertHTMLEqual(str(f['language']), """<select class="foo" name="language" required>
<option value="P" selected="selected">Python</option>
<option value="J">Java</option>
</select>""")
@@ -549,10 +565,10 @@ class FormsTestCase(SimpleTestCase):
language = ChoiceField()
f = FrameworkForm(auto_id=False)
- self.assertHTMLEqual(str(f['language']), """<select name="language">
+ self.assertHTMLEqual(str(f['language']), """<select name="language" required>
</select>""")
f.fields['language'].choices = [('P', 'Python'), ('J', 'Java')]
- self.assertHTMLEqual(str(f['language']), """<select name="language">
+ self.assertHTMLEqual(str(f['language']), """<select name="language" required>
<option value="P">Python</option>
<option value="J">Java</option>
</select>""")
@@ -565,18 +581,18 @@ class FormsTestCase(SimpleTestCase):
f = FrameworkForm(auto_id=False)
self.assertHTMLEqual(str(f['language']), """<ul>
-<li><label><input type="radio" name="language" value="P" /> Python</label></li>
-<li><label><input type="radio" name="language" value="J" /> Java</label></li>
+<li><label><input type="radio" name="language" value="P" required /> Python</label></li>
+<li><label><input type="radio" name="language" value="J" required /> Java</label></li>
</ul>""")
- self.assertHTMLEqual(f.as_table(), """<tr><th>Name:</th><td><input type="text" name="name" /></td></tr>
+ self.assertHTMLEqual(f.as_table(), """<tr><th>Name:</th><td><input type="text" name="name" required /></td></tr>
<tr><th>Language:</th><td><ul>
-<li><label><input type="radio" name="language" value="P" /> Python</label></li>
-<li><label><input type="radio" name="language" value="J" /> Java</label></li>
+<li><label><input type="radio" name="language" value="P" required /> Python</label></li>
+<li><label><input type="radio" name="language" value="J" required /> Java</label></li>
</ul></td></tr>""")
- self.assertHTMLEqual(f.as_ul(), """<li>Name: <input type="text" name="name" /></li>
+ self.assertHTMLEqual(f.as_ul(), """<li>Name: <input type="text" name="name" required /></li>
<li>Language: <ul>
-<li><label><input type="radio" name="language" value="P" /> Python</label></li>
-<li><label><input type="radio" name="language" value="J" /> Java</label></li>
+<li><label><input type="radio" name="language" value="P" required /> Python</label></li>
+<li><label><input type="radio" name="language" value="J" required /> Java</label></li>
</ul></li>""")
# Regarding auto_id and <label>, RadioSelect is a special case. Each radio button
@@ -586,8 +602,10 @@ class FormsTestCase(SimpleTestCase):
self.assertHTMLEqual(
str(f['language']),
"""<ul id="id_language">
-<li><label for="id_language_0"><input type="radio" id="id_language_0" value="P" name="language" /> Python</label></li>
-<li><label for="id_language_1"><input type="radio" id="id_language_1" value="J" name="language" /> Java</label></li>
+<li><label for="id_language_0"><input type="radio" id="id_language_0" value="P" name="language" required />
+Python</label></li>
+<li><label for="id_language_1"><input type="radio" id="id_language_1" value="J" name="language" required />
+Java</label></li>
</ul>"""
)
@@ -596,26 +614,32 @@ class FormsTestCase(SimpleTestCase):
# ID of the *first* radio button.
self.assertHTMLEqual(
f.as_table(),
- """<tr><th><label for="id_name">Name:</label></th><td><input type="text" name="name" id="id_name" /></td></tr>
+ """<tr><th><label for="id_name">Name:</label></th><td><input type="text" name="name" id="id_name" required /></td></tr>
<tr><th><label for="id_language_0">Language:</label></th><td><ul id="id_language">
-<li><label for="id_language_0"><input type="radio" id="id_language_0" value="P" name="language" /> Python</label></li>
-<li><label for="id_language_1"><input type="radio" id="id_language_1" value="J" name="language" /> Java</label></li>
+<li><label for="id_language_0"><input type="radio" id="id_language_0" value="P" name="language" required />
+Python</label></li>
+<li><label for="id_language_1"><input type="radio" id="id_language_1" value="J" name="language" required />
+Java</label></li>
</ul></td></tr>"""
)
self.assertHTMLEqual(
f.as_ul(),
- """<li><label for="id_name">Name:</label> <input type="text" name="name" id="id_name" /></li>
+ """<li><label for="id_name">Name:</label> <input type="text" name="name" id="id_name" required /></li>
<li><label for="id_language_0">Language:</label> <ul id="id_language">
-<li><label for="id_language_0"><input type="radio" id="id_language_0" value="P" name="language" /> Python</label></li>
-<li><label for="id_language_1"><input type="radio" id="id_language_1" value="J" name="language" /> Java</label></li>
+<li><label for="id_language_0"><input type="radio" id="id_language_0" value="P" name="language" required />
+Python</label></li>
+<li><label for="id_language_1"><input type="radio" id="id_language_1" value="J" name="language" required />
+Java</label></li>
</ul></li>"""
)
self.assertHTMLEqual(
f.as_p(),
- """<p><label for="id_name">Name:</label> <input type="text" name="name" id="id_name" /></p>
+ """<p><label for="id_name">Name:</label> <input type="text" name="name" id="id_name" required /></p>
<p><label for="id_language_0">Language:</label> <ul id="id_language">
-<li><label for="id_language_0"><input type="radio" id="id_language_0" value="P" name="language" /> Python</label></li>
-<li><label for="id_language_1"><input type="radio" id="id_language_1" value="J" name="language" /> Java</label></li>
+<li><label for="id_language_0"><input type="radio" id="id_language_0" value="P" name="language" required />
+Python</label></li>
+<li><label for="id_language_1"><input type="radio" id="id_language_1" value="J" name="language" required />
+Java</label></li>
</ul></p>"""
)
@@ -681,7 +705,7 @@ class FormsTestCase(SimpleTestCase):
composers = MultipleChoiceField()
f = SongForm(auto_id=False)
- self.assertHTMLEqual(str(f['composers']), """<select multiple="multiple" name="composers">
+ self.assertHTMLEqual(str(f['composers']), """<select multiple="multiple" name="composers" required>
</select>""")
class SongForm(Form):
@@ -689,13 +713,13 @@ class FormsTestCase(SimpleTestCase):
composers = MultipleChoiceField(choices=[('J', 'John Lennon'), ('P', 'Paul McCartney')])
f = SongForm(auto_id=False)
- self.assertHTMLEqual(str(f['composers']), """<select multiple="multiple" name="composers">
+ self.assertHTMLEqual(str(f['composers']), """<select multiple="multiple" name="composers" required>
<option value="J">John Lennon</option>
<option value="P">Paul McCartney</option>
</select>""")
f = SongForm({'name': 'Yesterday', 'composers': ['P']}, auto_id=False)
- self.assertHTMLEqual(str(f['name']), '<input type="text" name="name" value="Yesterday" />')
- self.assertHTMLEqual(str(f['composers']), """<select multiple="multiple" name="composers">
+ self.assertHTMLEqual(str(f['name']), '<input type="text" name="name" value="Yesterday" required />')
+ self.assertHTMLEqual(str(f['composers']), """<select multiple="multiple" name="composers" required>
<option value="J">John Lennon</option>
<option value="P" selected="selected">Paul McCartney</option>
</select>""")
@@ -761,8 +785,8 @@ class FormsTestCase(SimpleTestCase):
self.assertTrue(f.is_valid())
self.assertHTMLEqual(
str(f['when']),
- '<input type="text" name="when_0" value="1992-01-01" id="id_when_0" />'
- '<input type="text" name="when_1" value="01:01" id="id_when_1" />'
+ '<input type="text" name="when_0" value="1992-01-01" id="id_when_0" required />'
+ '<input type="text" name="when_1" value="01:01" id="id_when_1" required />'
)
self.assertHTMLEqual(
f['when'].as_hidden(),
@@ -781,18 +805,18 @@ class FormsTestCase(SimpleTestCase):
f = SongForm(auto_id=False)
self.assertHTMLEqual(str(f['composers']), """<ul>
-<li><label><input type="checkbox" name="composers" value="J" /> John Lennon</label></li>
-<li><label><input type="checkbox" name="composers" value="P" /> Paul McCartney</label></li>
+<li><label><input type="checkbox" name="composers" value="J" required /> John Lennon</label></li>
+<li><label><input type="checkbox" name="composers" value="P" required /> Paul McCartney</label></li>
</ul>""")
f = SongForm({'composers': ['J']}, auto_id=False)
self.assertHTMLEqual(str(f['composers']), """<ul>
-<li><label><input checked="checked" type="checkbox" name="composers" value="J" /> John Lennon</label></li>
-<li><label><input type="checkbox" name="composers" value="P" /> Paul McCartney</label></li>
+<li><label><input checked="checked" type="checkbox" name="composers" value="J" required /> John Lennon</label></li>
+<li><label><input type="checkbox" name="composers" value="P" required /> Paul McCartney</label></li>
</ul>""")
f = SongForm({'composers': ['J', 'P']}, auto_id=False)
self.assertHTMLEqual(str(f['composers']), """<ul>
-<li><label><input checked="checked" type="checkbox" name="composers" value="J" /> John Lennon</label></li>
-<li><label><input checked="checked" type="checkbox" name="composers" value="P" /> Paul McCartney</label></li>
+<li><label><input checked="checked" type="checkbox" name="composers" value="J" required /> John Lennon</label></li>
+<li><label><input checked="checked" type="checkbox" name="composers" value="P" required /> Paul McCartney</label></li>
</ul>""")
# Test iterating on individual checkboxes in a template
t = Template('{% for checkbox in form.composers %}<div class="mycheckbox">{{ checkbox }}</div>{% endfor %}')
@@ -817,9 +841,9 @@ class FormsTestCase(SimpleTestCase):
str(f['composers']),
"""<ul id="composers_id">
<li><label for="composers_id_0">
-<input type="checkbox" name="composers" value="J" id="composers_id_0" /> John Lennon</label></li>
+<input type="checkbox" name="composers" value="J" id="composers_id_0" required /> John Lennon</label></li>
<li><label for="composers_id_1">
-<input type="checkbox" name="composers" value="P" id="composers_id_1" /> Paul McCartney</label></li>
+<input type="checkbox" name="composers" value="P" id="composers_id_1" required /> Paul McCartney</label></li>
</ul>"""
)
@@ -864,7 +888,7 @@ class FormsTestCase(SimpleTestCase):
f = SongFormHidden(MultiValueDict(dict(name=['Yesterday'], composers=['J', 'P'])), auto_id=False)
self.assertHTMLEqual(
f.as_ul(),
- """<li>Name: <input type="text" name="name" value="Yesterday" />
+ """<li>Name: <input type="text" name="name" value="Yesterday" required />
<input type="hidden" name="composers" value="J" />
<input type="hidden" name="composers" value="P" /></li>"""
)
@@ -905,10 +929,10 @@ class FormsTestCase(SimpleTestCase):
f.as_table(),
"""<tr><th>&lt;em&gt;Special&lt;/em&gt; Field:</th><td>
<ul class="errorlist"><li>Something&#39;s wrong with &#39;Nothing to escape&#39;</li></ul>
-<input type="text" name="special_name" value="Nothing to escape" /></td></tr>
+<input type="text" name="special_name" value="Nothing to escape" required /></td></tr>
<tr><th><em>Special</em> Field:</th><td>
<ul class="errorlist"><li>'<b>Nothing to escape</b>' is a safe string</li></ul>
-<input type="text" name="special_safe_name" value="Nothing to escape" /></td></tr>"""
+<input type="text" name="special_safe_name" value="Nothing to escape" required /></td></tr>"""
)
f = EscapingForm({
'special_name': "Should escape < & > and <script>alert('xss')</script>",
@@ -920,10 +944,10 @@ class FormsTestCase(SimpleTestCase):
<ul class="errorlist"><li>Something&#39;s wrong with &#39;Should escape &lt; &amp; &gt; and
&lt;script&gt;alert(&#39;xss&#39;)&lt;/script&gt;&#39;</li></ul>
<input type="text" name="special_name"
-value="Should escape &lt; &amp; &gt; and &lt;script&gt;alert(&#39;xss&#39;)&lt;/script&gt;" /></td></tr>
+value="Should escape &lt; &amp; &gt; and &lt;script&gt;alert(&#39;xss&#39;)&lt;/script&gt;" required /></td></tr>
<tr><th><em>Special</em> Field:</th><td>
<ul class="errorlist"><li>'<b><i>Do not escape</i></b>' is a safe string</li></ul>
-<input type="text" name="special_safe_name" value="&lt;i&gt;Do not escape&lt;/i&gt;" /></td></tr>"""
+<input type="text" name="special_safe_name" value="&lt;i&gt;Do not escape&lt;/i&gt;" required /></td></tr>"""
)
def test_validating_multiple_fields(self):
@@ -1010,11 +1034,11 @@ value="Should escape &lt; &amp; &gt; and &lt;script&gt;alert(&#39;xss&#39;)&lt;/
f.as_table(),
"""<tr><th>Username:</th><td>
<ul class="errorlist"><li>This field is required.</li></ul>
-<input type="text" name="username" maxlength="10" /></td></tr>
+<input type="text" name="username" maxlength="10" required /></td></tr>
<tr><th>Password1:</th><td><ul class="errorlist"><li>This field is required.</li></ul>
-<input type="password" name="password1" /></td></tr>
+<input type="password" name="password1" required /></td></tr>
<tr><th>Password2:</th><td><ul class="errorlist"><li>This field is required.</li></ul>
-<input type="password" name="password2" /></td></tr>"""
+<input type="password" name="password2" required /></td></tr>"""
)
self.assertEqual(f.errors['username'], ['This field is required.'])
self.assertEqual(f.errors['password1'], ['This field is required.'])
@@ -1026,17 +1050,17 @@ value="Should escape &lt; &amp; &gt; and &lt;script&gt;alert(&#39;xss&#39;)&lt;/
f.as_table(),
"""<tr><td colspan="2">
<ul class="errorlist nonfield"><li>Please make sure your passwords match.</li></ul></td></tr>
-<tr><th>Username:</th><td><input type="text" name="username" value="adrian" maxlength="10" /></td></tr>
-<tr><th>Password1:</th><td><input type="password" name="password1" /></td></tr>
-<tr><th>Password2:</th><td><input type="password" name="password2" /></td></tr>"""
+<tr><th>Username:</th><td><input type="text" name="username" value="adrian" maxlength="10" required /></td></tr>
+<tr><th>Password1:</th><td><input type="password" name="password1" required /></td></tr>
+<tr><th>Password2:</th><td><input type="password" name="password2" required /></td></tr>"""
)
self.assertHTMLEqual(
f.as_ul(),
"""<li><ul class="errorlist nonfield">
<li>Please make sure your passwords match.</li></ul></li>
-<li>Username: <input type="text" name="username" value="adrian" maxlength="10" /></li>
-<li>Password1: <input type="password" name="password1" /></li>
-<li>Password2: <input type="password" name="password2" /></li>"""
+<li>Username: <input type="text" name="username" value="adrian" maxlength="10" required /></li>
+<li>Password1: <input type="password" name="password1" required /></li>
+<li>Password2: <input type="password" name="password2" required /></li>"""
)
f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'foo'}, auto_id=False)
@@ -1160,9 +1184,9 @@ value="Should escape &lt; &amp; &gt; and &lt;script&gt;alert(&#39;xss&#39;)&lt;/
p = Person(auto_id=False)
self.assertHTMLEqual(
p.as_table(),
- """<tr><th>First name:</th><td><input type="text" name="first_name" /></td></tr>
-<tr><th>Last name:</th><td><input type="text" name="last_name" /></td></tr>
-<tr><th>Birthday:</th><td><input type="text" name="birthday" /></td></tr>"""
+ """<tr><th>First name:</th><td><input type="text" name="first_name" required /></td></tr>
+<tr><th>Last name:</th><td><input type="text" name="last_name" required /></td></tr>
+<tr><th>Birthday:</th><td><input type="text" name="birthday" required /></td></tr>"""
)
# Instances of a dynamic Form do not persist fields from one Form instance to
@@ -1178,15 +1202,15 @@ value="Should escape &lt; &amp; &gt; and &lt;script&gt;alert(&#39;xss&#39;)&lt;/
my_form = MyForm(field_list=field_list)
self.assertHTMLEqual(
my_form.as_table(),
- """<tr><th>Field1:</th><td><input type="text" name="field1" /></td></tr>
-<tr><th>Field2:</th><td><input type="text" name="field2" /></td></tr>"""
+ """<tr><th>Field1:</th><td><input type="text" name="field1" required /></td></tr>
+<tr><th>Field2:</th><td><input type="text" name="field2" required /></td></tr>"""
)
field_list = [('field3', CharField()), ('field4', CharField())]
my_form = MyForm(field_list=field_list)
self.assertHTMLEqual(
my_form.as_table(),
- """<tr><th>Field3:</th><td><input type="text" name="field3" /></td></tr>
-<tr><th>Field4:</th><td><input type="text" name="field4" /></td></tr>"""
+ """<tr><th>Field3:</th><td><input type="text" name="field3" required /></td></tr>
+<tr><th>Field4:</th><td><input type="text" name="field4" required /></td></tr>"""
)
class MyForm(Form):
@@ -1203,19 +1227,19 @@ value="Should escape &lt; &amp; &gt; and &lt;script&gt;alert(&#39;xss&#39;)&lt;/
my_form = MyForm(field_list=field_list)
self.assertHTMLEqual(
my_form.as_table(),
- """<tr><th>Default field 1:</th><td><input type="text" name="default_field_1" /></td></tr>
-<tr><th>Default field 2:</th><td><input type="text" name="default_field_2" /></td></tr>
-<tr><th>Field1:</th><td><input type="text" name="field1" /></td></tr>
-<tr><th>Field2:</th><td><input type="text" name="field2" /></td></tr>"""
+ """<tr><th>Default field 1:</th><td><input type="text" name="default_field_1" required /></td></tr>
+<tr><th>Default field 2:</th><td><input type="text" name="default_field_2" required /></td></tr>
+<tr><th>Field1:</th><td><input type="text" name="field1" required /></td></tr>
+<tr><th>Field2:</th><td><input type="text" name="field2" required /></td></tr>"""
)
field_list = [('field3', CharField()), ('field4', CharField())]
my_form = MyForm(field_list=field_list)
self.assertHTMLEqual(
my_form.as_table(),
- """<tr><th>Default field 1:</th><td><input type="text" name="default_field_1" /></td></tr>
-<tr><th>Default field 2:</th><td><input type="text" name="default_field_2" /></td></tr>
-<tr><th>Field3:</th><td><input type="text" name="field3" /></td></tr>
-<tr><th>Field4:</th><td><input type="text" name="field4" /></td></tr>"""
+ """<tr><th>Default field 1:</th><td><input type="text" name="default_field_1" required /></td></tr>
+<tr><th>Default field 2:</th><td><input type="text" name="default_field_2" required /></td></tr>
+<tr><th>Field3:</th><td><input type="text" name="field3" required /></td></tr>
+<tr><th>Field4:</th><td><input type="text" name="field4" required /></td></tr>"""
)
# Similarly, changes to field attributes do not persist from one Form instance
@@ -1313,20 +1337,21 @@ value="Should escape &lt; &amp; &gt; and &lt;script&gt;alert(&#39;xss&#39;)&lt;/
p = Person(auto_id=False)
self.assertHTMLEqual(
p.as_table(),
- """<tr><th>First name:</th><td><input type="text" name="first_name" /></td></tr>
-<tr><th>Last name:</th><td><input type="text" name="last_name" /></td></tr>
-<tr><th>Birthday:</th><td><input type="text" name="birthday" /><input type="hidden" name="hidden_text" /></td></tr>"""
+ """<tr><th>First name:</th><td><input type="text" name="first_name" required /></td></tr>
+<tr><th>Last name:</th><td><input type="text" name="last_name" required /></td></tr>
+<tr><th>Birthday:</th>
+<td><input type="text" name="birthday" required /><input type="hidden" name="hidden_text" /></td></tr>"""
)
self.assertHTMLEqual(
p.as_ul(),
- """<li>First name: <input type="text" name="first_name" /></li>
-<li>Last name: <input type="text" name="last_name" /></li>
-<li>Birthday: <input type="text" name="birthday" /><input type="hidden" name="hidden_text" /></li>"""
+ """<li>First name: <input type="text" name="first_name" required /></li>
+<li>Last name: <input type="text" name="last_name" required /></li>
+<li>Birthday: <input type="text" name="birthday" required /><input type="hidden" name="hidden_text" /></li>"""
)
self.assertHTMLEqual(
- p.as_p(), """<p>First name: <input type="text" name="first_name" /></p>
-<p>Last name: <input type="text" name="last_name" /></p>
-<p>Birthday: <input type="text" name="birthday" /><input type="hidden" name="hidden_text" /></p>"""
+ p.as_p(), """<p>First name: <input type="text" name="first_name" required /></p>
+<p>Last name: <input type="text" name="last_name" required /></p>
+<p>Birthday: <input type="text" name="birthday" required /><input type="hidden" name="hidden_text" /></p>"""
)
# With auto_id set, a HiddenInput still gets an ID, but it doesn't get a label.
@@ -1334,31 +1359,31 @@ value="Should escape &lt; &amp; &gt; and &lt;script&gt;alert(&#39;xss&#39;)&lt;/
self.assertHTMLEqual(
p.as_table(),
"""<tr><th><label for="id_first_name">First name:</label></th><td>
-<input type="text" name="first_name" id="id_first_name" /></td></tr>
+<input type="text" name="first_name" id="id_first_name" required /></td></tr>
<tr><th><label for="id_last_name">Last name:</label></th><td>
-<input type="text" name="last_name" id="id_last_name" /></td></tr>
+<input type="text" name="last_name" id="id_last_name" required /></td></tr>
<tr><th><label for="id_birthday">Birthday:</label></th><td>
-<input type="text" name="birthday" id="id_birthday" />
+<input type="text" name="birthday" id="id_birthday" required />
<input type="hidden" name="hidden_text" id="id_hidden_text" /></td></tr>"""
)
self.assertHTMLEqual(
p.as_ul(),
"""<li><label for="id_first_name">First name:</label>
-<input type="text" name="first_name" id="id_first_name" /></li>
+<input type="text" name="first_name" id="id_first_name" required /></li>
<li><label for="id_last_name">Last name:</label>
-<input type="text" name="last_name" id="id_last_name" /></li>
+<input type="text" name="last_name" id="id_last_name" required /></li>
<li><label for="id_birthday">Birthday:</label>
-<input type="text" name="birthday" id="id_birthday" />
+<input type="text" name="birthday" id="id_birthday" required />
<input type="hidden" name="hidden_text" id="id_hidden_text" /></li>"""
)
self.assertHTMLEqual(
p.as_p(),
"""<p><label for="id_first_name">First name:</label>
-<input type="text" name="first_name" id="id_first_name" /></p>
+<input type="text" name="first_name" id="id_first_name" required /></p>
<p><label for="id_last_name">Last name:</label>
-<input type="text" name="last_name" id="id_last_name" /></p>
+<input type="text" name="last_name" id="id_last_name" required /></p>
<p><label for="id_birthday">Birthday:</label>
-<input type="text" name="birthday" id="id_birthday" />
+<input type="text" name="birthday" id="id_birthday" required />
<input type="hidden" name="hidden_text" id="id_hidden_text" /></p>"""
)
@@ -1371,26 +1396,26 @@ value="Should escape &lt; &amp; &gt; and &lt;script&gt;alert(&#39;xss&#39;)&lt;/
p.as_table(),
"""<tr><td colspan="2">
<ul class="errorlist nonfield"><li>(Hidden field hidden_text) This field is required.</li></ul></td></tr>
-<tr><th>First name:</th><td><input type="text" name="first_name" value="John" /></td></tr>
-<tr><th>Last name:</th><td><input type="text" name="last_name" value="Lennon" /></td></tr>
-<tr><th>Birthday:</th><td><input type="text" name="birthday" value="1940-10-9" />
+<tr><th>First name:</th><td><input type="text" name="first_name" value="John" required /></td></tr>
+<tr><th>Last name:</th><td><input type="text" name="last_name" value="Lennon" required /></td></tr>
+<tr><th>Birthday:</th><td><input type="text" name="birthday" value="1940-10-9" required />
<input type="hidden" name="hidden_text" /></td></tr>"""
)
self.assertHTMLEqual(
p.as_ul(),
"""<li><ul class="errorlist nonfield"><li>(Hidden field hidden_text) This field is required.</li></ul></li>
-<li>First name: <input type="text" name="first_name" value="John" /></li>
-<li>Last name: <input type="text" name="last_name" value="Lennon" /></li>
-<li>Birthday: <input type="text" name="birthday" value="1940-10-9" />
+<li>First name: <input type="text" name="first_name" value="John" required /></li>
+<li>Last name: <input type="text" name="last_name" value="Lennon" required /></li>
+<li>Birthday: <input type="text" name="birthday" value="1940-10-9" required />
<input type="hidden" name="hidden_text" /></li>"""
)
self.assertHTMLEqual(
p.as_p(),
"""<ul class="errorlist nonfield"><li>(Hidden field hidden_text) This field is required.</li></ul>
-<p>First name: <input type="text" name="first_name" value="John" /></p>
-<p>Last name: <input type="text" name="last_name" value="Lennon" /></p>
-<p>Birthday: <input type="text" name="birthday" value="1940-10-9" /
-><input type="hidden" name="hidden_text" /></p>"""
+<p>First name: <input type="text" name="first_name" value="John" required /></p>
+<p>Last name: <input type="text" name="last_name" value="Lennon" required /></p>
+<p>Birthday: <input type="text" name="birthday" value="1940-10-9" required />
+<input type="hidden" name="hidden_text" /></p>"""
)
# A corner case: It's possible for a form to have only HiddenInputs.
@@ -1422,20 +1447,20 @@ value="Should escape &lt; &amp; &gt; and &lt;script&gt;alert(&#39;xss&#39;)&lt;/
field14 = CharField()
p = TestForm(auto_id=False)
- self.assertHTMLEqual(p.as_table(), """<tr><th>Field1:</th><td><input type="text" name="field1" /></td></tr>
-<tr><th>Field2:</th><td><input type="text" name="field2" /></td></tr>
-<tr><th>Field3:</th><td><input type="text" name="field3" /></td></tr>
-<tr><th>Field4:</th><td><input type="text" name="field4" /></td></tr>
-<tr><th>Field5:</th><td><input type="text" name="field5" /></td></tr>
-<tr><th>Field6:</th><td><input type="text" name="field6" /></td></tr>
-<tr><th>Field7:</th><td><input type="text" name="field7" /></td></tr>
-<tr><th>Field8:</th><td><input type="text" name="field8" /></td></tr>
-<tr><th>Field9:</th><td><input type="text" name="field9" /></td></tr>
-<tr><th>Field10:</th><td><input type="text" name="field10" /></td></tr>
-<tr><th>Field11:</th><td><input type="text" name="field11" /></td></tr>
-<tr><th>Field12:</th><td><input type="text" name="field12" /></td></tr>
-<tr><th>Field13:</th><td><input type="text" name="field13" /></td></tr>
-<tr><th>Field14:</th><td><input type="text" name="field14" /></td></tr>""")
+ self.assertHTMLEqual(p.as_table(), """<tr><th>Field1:</th><td><input type="text" name="field1" required /></td></tr>
+<tr><th>Field2:</th><td><input type="text" name="field2" required /></td></tr>
+<tr><th>Field3:</th><td><input type="text" name="field3" required /></td></tr>
+<tr><th>Field4:</th><td><input type="text" name="field4" required /></td></tr>
+<tr><th>Field5:</th><td><input type="text" name="field5" required /></td></tr>
+<tr><th>Field6:</th><td><input type="text" name="field6" required /></td></tr>
+<tr><th>Field7:</th><td><input type="text" name="field7" required /></td></tr>
+<tr><th>Field8:</th><td><input type="text" name="field8" required /></td></tr>
+<tr><th>Field9:</th><td><input type="text" name="field9" required /></td></tr>
+<tr><th>Field10:</th><td><input type="text" name="field10" required /></td></tr>
+<tr><th>Field11:</th><td><input type="text" name="field11" required /></td></tr>
+<tr><th>Field12:</th><td><input type="text" name="field12" required /></td></tr>
+<tr><th>Field13:</th><td><input type="text" name="field13" required /></td></tr>
+<tr><th>Field14:</th><td><input type="text" name="field14" required /></td></tr>""")
def test_explicit_field_order(self):
class TestFormParent(Form):
@@ -1494,10 +1519,10 @@ value="Should escape &lt; &amp; &gt; and &lt;script&gt;alert(&#39;xss&#39;)&lt;/
p = UserRegistration(auto_id=False)
self.assertHTMLEqual(
p.as_ul(),
- """<li>Username: <input type="text" name="username" maxlength="10" /></li>
-<li>Password: <input type="password" name="password" maxlength="10" /></li>
-<li>Realname: <input type="text" name="realname" maxlength="10" /></li>
-<li>Address: <input type="text" name="address" /></li>"""
+ """<li>Username: <input type="text" name="username" maxlength="10" required /></li>
+<li>Password: <input type="password" name="password" maxlength="10" required /></li>
+<li>Realname: <input type="text" name="realname" maxlength="10" required /></li>
+<li>Address: <input type="text" name="address" required /></li>"""
)
# If you specify a custom "attrs" that includes the "maxlength" attribute,
@@ -1510,8 +1535,8 @@ value="Should escape &lt; &amp; &gt; and &lt;script&gt;alert(&#39;xss&#39;)&lt;/
p = UserRegistration(auto_id=False)
self.assertHTMLEqual(
p.as_ul(),
- """<li>Username: <input type="text" name="username" maxlength="10" /></li>
-<li>Password: <input type="password" name="password" maxlength="10" /></li>"""
+ """<li>Username: <input type="text" name="username" maxlength="10" required /></li>
+<li>Password: <input type="password" name="password" maxlength="10" required /></li>"""
)
def test_specifying_labels(self):
@@ -1526,9 +1551,9 @@ value="Should escape &lt; &amp; &gt; and &lt;script&gt;alert(&#39;xss&#39;)&lt;/
p = UserRegistration(auto_id=False)
self.assertHTMLEqual(
p.as_ul(),
- """<li>Your username: <input type="text" name="username" maxlength="10" /></li>
-<li>Password1: <input type="password" name="password1" /></li>
-<li>Contraseña (de nuevo): <input type="password" name="password2" /></li>"""
+ """<li>Your username: <input type="text" name="username" maxlength="10" required /></li>
+<li>Password1: <input type="password" name="password1" required /></li>
+<li>Contraseña (de nuevo): <input type="password" name="password2" required /></li>"""
)
# Labels for as_* methods will only end in a colon if they don't end in other
@@ -1542,19 +1567,19 @@ value="Should escape &lt; &amp; &gt; and &lt;script&gt;alert(&#39;xss&#39;)&lt;/
self.assertHTMLEqual(
Questions(auto_id=False).as_p(),
- """<p>The first question: <input type="text" name="q1" /></p>
-<p>What is your name? <input type="text" name="q2" /></p>
-<p>The answer to life is: <input type="text" name="q3" /></p>
-<p>Answer this question! <input type="text" name="q4" /></p>
-<p>The last question. Period. <input type="text" name="q5" /></p>"""
+ """<p>The first question: <input type="text" name="q1" required /></p>
+<p>What is your name? <input type="text" name="q2" required /></p>
+<p>The answer to life is: <input type="text" name="q3" required /></p>
+<p>Answer this question! <input type="text" name="q4" required /></p>
+<p>The last question. Period. <input type="text" name="q5" required /></p>"""
)
self.assertHTMLEqual(
Questions().as_p(),
- """<p><label for="id_q1">The first question:</label> <input type="text" name="q1" id="id_q1" /></p>
-<p><label for="id_q2">What is your name?</label> <input type="text" name="q2" id="id_q2" /></p>
-<p><label for="id_q3">The answer to life is:</label> <input type="text" name="q3" id="id_q3" /></p>
-<p><label for="id_q4">Answer this question!</label> <input type="text" name="q4" id="id_q4" /></p>
-<p><label for="id_q5">The last question. Period.</label> <input type="text" name="q5" id="id_q5" /></p>"""
+ """<p><label for="id_q1">The first question:</label> <input type="text" name="q1" id="id_q1" required /></p>
+<p><label for="id_q2">What is your name?</label> <input type="text" name="q2" id="id_q2" required /></p>
+<p><label for="id_q3">The answer to life is:</label> <input type="text" name="q3" id="id_q3" required /></p>
+<p><label for="id_q4">Answer this question!</label> <input type="text" name="q4" id="id_q4" required /></p>
+<p><label for="id_q5">The last question. Period.</label> <input type="text" name="q5" id="id_q5" required /></p>"""
)
# If a label is set to the empty string for a field, that field won't get a label.
@@ -1563,13 +1588,14 @@ value="Should escape &lt; &amp; &gt; and &lt;script&gt;alert(&#39;xss&#39;)&lt;/
password = CharField(widget=PasswordInput)
p = UserRegistration(auto_id=False)
- self.assertHTMLEqual(p.as_ul(), """<li> <input type="text" name="username" maxlength="10" /></li>
-<li>Password: <input type="password" name="password" /></li>""")
+ self.assertHTMLEqual(p.as_ul(), """<li> <input type="text" name="username" maxlength="10" required /></li>
+<li>Password: <input type="password" name="password" required /></li>""")
p = UserRegistration(auto_id='id_%s')
self.assertHTMLEqual(
p.as_ul(),
- """<li> <input id="id_username" type="text" name="username" maxlength="10" /></li>
-<li><label for="id_password">Password:</label> <input type="password" name="password" id="id_password" /></li>"""
+ """<li> <input id="id_username" type="text" name="username" maxlength="10" required /></li>
+<li><label for="id_password">Password:</label>
+<input type="password" name="password" id="id_password" required /></li>"""
)
# If label is None, Django will auto-create the label from the field name. This
@@ -1581,15 +1607,16 @@ value="Should escape &lt; &amp; &gt; and &lt;script&gt;alert(&#39;xss&#39;)&lt;/
p = UserRegistration(auto_id=False)
self.assertHTMLEqual(
p.as_ul(),
- """<li>Username: <input type="text" name="username" maxlength="10" /></li>
-<li>Password: <input type="password" name="password" /></li>"""
+ """<li>Username: <input type="text" name="username" maxlength="10" required /></li>
+<li>Password: <input type="password" name="password" required /></li>"""
)
p = UserRegistration(auto_id='id_%s')
self.assertHTMLEqual(
p.as_ul(),
"""<li><label for="id_username">Username:</label>
-<input id="id_username" type="text" name="username" maxlength="10" /></li>
-<li><label for="id_password">Password:</label> <input type="password" name="password" id="id_password" /></li>"""
+<input id="id_username" type="text" name="username" maxlength="10" required /></li>
+<li><label for="id_password">Password:</label>
+<input type="password" name="password" id="id_password" required /></li>"""
)
def test_label_suffix(self):
@@ -1604,26 +1631,26 @@ value="Should escape &lt; &amp; &gt; and &lt;script&gt;alert(&#39;xss&#39;)&lt;/
answer = CharField(label='Secret answer', label_suffix=' =')
f = FavoriteForm(auto_id=False)
- self.assertHTMLEqual(f.as_ul(), """<li>Favorite color? <input type="text" name="color" /></li>
-<li>Favorite animal: <input type="text" name="animal" /></li>
-<li>Secret answer = <input type="text" name="answer" /></li>""")
+ self.assertHTMLEqual(f.as_ul(), """<li>Favorite color? <input type="text" name="color" required /></li>
+<li>Favorite animal: <input type="text" name="animal" required /></li>
+<li>Secret answer = <input type="text" name="answer" required /></li>""")
f = FavoriteForm(auto_id=False, label_suffix='?')
- self.assertHTMLEqual(f.as_ul(), """<li>Favorite color? <input type="text" name="color" /></li>
-<li>Favorite animal? <input type="text" name="animal" /></li>
-<li>Secret answer = <input type="text" name="answer" /></li>""")
+ self.assertHTMLEqual(f.as_ul(), """<li>Favorite color? <input type="text" name="color" required /></li>
+<li>Favorite animal? <input type="text" name="animal" required /></li>
+<li>Secret answer = <input type="text" name="answer" required /></li>""")
f = FavoriteForm(auto_id=False, label_suffix='')
- self.assertHTMLEqual(f.as_ul(), """<li>Favorite color? <input type="text" name="color" /></li>
-<li>Favorite animal <input type="text" name="animal" /></li>
-<li>Secret answer = <input type="text" name="answer" /></li>""")
+ self.assertHTMLEqual(f.as_ul(), """<li>Favorite color? <input type="text" name="color" required /></li>
+<li>Favorite animal <input type="text" name="animal" required /></li>
+<li>Secret answer = <input type="text" name="answer" required /></li>""")
f = FavoriteForm(auto_id=False, label_suffix='\u2192')
self.assertHTMLEqual(
f.as_ul(),
- '<li>Favorite color? <input type="text" name="color" /></li>\n'
- '<li>Favorite animal\u2192 <input type="text" name="animal" /></li>\n'
- '<li>Secret answer = <input type="text" name="answer" /></li>'
+ '<li>Favorite color? <input type="text" name="color" required /></li>\n'
+ '<li>Favorite animal\u2192 <input type="text" name="animal" required /></li>\n'
+ '<li>Secret answer = <input type="text" name="answer" required /></li>'
)
def test_initial_data(self):
@@ -1640,8 +1667,8 @@ value="Should escape &lt; &amp; &gt; and &lt;script&gt;alert(&#39;xss&#39;)&lt;/
p = UserRegistration(auto_id=False)
self.assertHTMLEqual(
p.as_ul(),
- """<li>Username: <input type="text" name="username" value="django" maxlength="10" /></li>
-<li>Password: <input type="password" name="password" /></li>"""
+ """<li>Username: <input type="text" name="username" value="django" maxlength="10" required /></li>
+<li>Password: <input type="password" name="password" required /></li>"""
)
# Here, we're submitting data, so the initial value will *not* be displayed.
@@ -1649,24 +1676,24 @@ value="Should escape &lt; &amp; &gt; and &lt;script&gt;alert(&#39;xss&#39;)&lt;/
self.assertHTMLEqual(
p.as_ul(),
"""<li><ul class="errorlist"><li>This field is required.</li></ul>
-Username: <input type="text" name="username" maxlength="10" /></li>
+Username: <input type="text" name="username" maxlength="10" required /></li>
<li><ul class="errorlist"><li>This field is required.</li></ul>
-Password: <input type="password" name="password" /></li>"""
+Password: <input type="password" name="password" required /></li>"""
)
p = UserRegistration({'username': ''}, auto_id=False)
self.assertHTMLEqual(
p.as_ul(),
"""<li><ul class="errorlist"><li>This field is required.</li></ul>
-Username: <input type="text" name="username" maxlength="10" /></li>
+Username: <input type="text" name="username" maxlength="10" required /></li>
<li><ul class="errorlist"><li>This field is required.</li></ul>
-Password: <input type="password" name="password" /></li>"""
+Password: <input type="password" name="password" required /></li>"""
)
p = UserRegistration({'username': 'foo'}, auto_id=False)
self.assertHTMLEqual(
p.as_ul(),
- """<li>Username: <input type="text" name="username" value="foo" maxlength="10" /></li>
+ """<li>Username: <input type="text" name="username" value="foo" maxlength="10" required /></li>
<li><ul class="errorlist"><li>This field is required.</li></ul>
-Password: <input type="password" name="password" /></li>"""
+Password: <input type="password" name="password" required /></li>"""
)
# An 'initial' value is *not* used as a fallback if data is not provided. In this
@@ -1690,14 +1717,14 @@ Password: <input type="password" name="password" /></li>"""
p = UserRegistration(initial={'username': 'django'}, auto_id=False)
self.assertHTMLEqual(
p.as_ul(),
- """<li>Username: <input type="text" name="username" value="django" maxlength="10" /></li>
-<li>Password: <input type="password" name="password" /></li>"""
+ """<li>Username: <input type="text" name="username" value="django" maxlength="10" required /></li>
+<li>Password: <input type="password" name="password" required /></li>"""
)
p = UserRegistration(initial={'username': 'stephane'}, auto_id=False)
self.assertHTMLEqual(
p.as_ul(),
- """<li>Username: <input type="text" name="username" value="stephane" maxlength="10" /></li>
-<li>Password: <input type="password" name="password" /></li>"""
+ """<li>Username: <input type="text" name="username" value="stephane" maxlength="10" required /></li>
+<li>Password: <input type="password" name="password" required /></li>"""
)
# The 'initial' parameter is meaningless if you pass data.
@@ -1705,23 +1732,23 @@ Password: <input type="password" name="password" /></li>"""
self.assertHTMLEqual(
p.as_ul(),
"""<li><ul class="errorlist"><li>This field is required.</li></ul>
-Username: <input type="text" name="username" maxlength="10" /></li>
+Username: <input type="text" name="username" maxlength="10" required /></li>
<li><ul class="errorlist"><li>This field is required.</li></ul>
-Password: <input type="password" name="password" /></li>"""
+Password: <input type="password" name="password" required /></li>"""
)
p = UserRegistration({'username': ''}, initial={'username': 'django'}, auto_id=False)
self.assertHTMLEqual(
p.as_ul(),
"""<li><ul class="errorlist"><li>This field is required.</li></ul>
-Username: <input type="text" name="username" maxlength="10" /></li>
+Username: <input type="text" name="username" maxlength="10" required /></li>
<li><ul class="errorlist"><li>This field is required.</li></ul>
-Password: <input type="password" name="password" /></li>"""
+Password: <input type="password" name="password" required /></li>"""
)
p = UserRegistration({'username': 'foo'}, initial={'username': 'django'}, auto_id=False)
self.assertHTMLEqual(
- p.as_ul(), """<li>Username: <input type="text" name="username" value="foo" maxlength="10" /></li>
+ p.as_ul(), """<li>Username: <input type="text" name="username" value="foo" maxlength="10" required /></li>
<li><ul class="errorlist"><li>This field is required.</li></ul>
-Password: <input type="password" name="password" /></li>"""
+Password: <input type="password" name="password" required /></li>"""
)
# A dynamic 'initial' value is *not* used as a fallback if data is not provided.
@@ -1740,8 +1767,8 @@ Password: <input type="password" name="password" /></li>"""
p = UserRegistration(initial={'username': 'babik'}, auto_id=False)
self.assertHTMLEqual(
p.as_ul(),
- """<li>Username: <input type="text" name="username" value="babik" maxlength="10" /></li>
-<li>Password: <input type="password" name="password" /></li>"""
+ """<li>Username: <input type="text" name="username" value="babik" maxlength="10" required /></li>
+<li>Password: <input type="password" name="password" required /></li>"""
)
def test_callable_initial_data(self):
@@ -1769,9 +1796,9 @@ Password: <input type="password" name="password" /></li>"""
p = UserRegistration(initial={'username': initial_django, 'options': initial_options}, auto_id=False)
self.assertHTMLEqual(
p.as_ul(),
- """<li>Username: <input type="text" name="username" value="django" maxlength="10" /></li>
-<li>Password: <input type="password" name="password" /></li>
-<li>Options: <select multiple="multiple" name="options">
+ """<li>Username: <input type="text" name="username" value="django" maxlength="10" required /></li>
+<li>Password: <input type="password" name="password" required /></li>
+<li>Options: <select multiple="multiple" name="options" required>
<option value="f" selected="selected">foo</option>
<option value="b" selected="selected">bar</option>
<option value="w">whiz</option>
@@ -1783,11 +1810,11 @@ Password: <input type="password" name="password" /></li>"""
self.assertHTMLEqual(
p.as_ul(),
"""<li><ul class="errorlist"><li>This field is required.</li></ul>
-Username: <input type="text" name="username" maxlength="10" /></li>
+Username: <input type="text" name="username" maxlength="10" required /></li>
<li><ul class="errorlist"><li>This field is required.</li></ul>
-Password: <input type="password" name="password" /></li>
+Password: <input type="password" name="password" required /></li>
<li><ul class="errorlist"><li>This field is required.</li></ul>
-Options: <select multiple="multiple" name="options">
+Options: <select multiple="multiple" name="options" required>
<option value="f">foo</option>
<option value="b">bar</option>
<option value="w">whiz</option>
@@ -1797,11 +1824,11 @@ Options: <select multiple="multiple" name="options">
self.assertHTMLEqual(
p.as_ul(),
"""<li><ul class="errorlist"><li>This field is required.</li></ul>
- Username: <input type="text" name="username" maxlength="10" /></li>
+ Username: <input type="text" name="username" maxlength="10" required /></li>
<li><ul class="errorlist"><li>This field is required.</li></ul>
-Password: <input type="password" name="password" /></li>
+Password: <input type="password" name="password" required /></li>
<li><ul class="errorlist"><li>This field is required.</li></ul>
-Options: <select multiple="multiple" name="options">
+Options: <select multiple="multiple" name="options" required>
<option value="f">foo</option>
<option value="b">bar</option>
<option value="w">whiz</option>
@@ -1812,10 +1839,10 @@ Options: <select multiple="multiple" name="options">
)
self.assertHTMLEqual(
p.as_ul(),
- """<li>Username: <input type="text" name="username" value="foo" maxlength="10" /></li>
+ """<li>Username: <input type="text" name="username" value="foo" maxlength="10" required /></li>
<li><ul class="errorlist"><li>This field is required.</li></ul>
-Password: <input type="password" name="password" /></li>
-<li>Options: <select multiple="multiple" name="options">
+Password: <input type="password" name="password" required /></li>
+<li>Options: <select multiple="multiple" name="options" required>
<option value="f" selected="selected">foo</option>
<option value="b" selected="selected">bar</option>
<option value="w">whiz</option>
@@ -1842,9 +1869,9 @@ Password: <input type="password" name="password" /></li>
p = UserRegistration(auto_id=False)
self.assertHTMLEqual(
p.as_ul(),
- """<li>Username: <input type="text" name="username" value="django" maxlength="10" /></li>
-<li>Password: <input type="password" name="password" /></li>
-<li>Options: <select multiple="multiple" name="options">
+ """<li>Username: <input type="text" name="username" value="django" maxlength="10" required /></li>
+<li>Password: <input type="password" name="password" required /></li>
+<li>Options: <select multiple="multiple" name="options" required>
<option value="f">foo</option>
<option value="b" selected="selected">bar</option>
<option value="w" selected="selected">whiz</option>
@@ -1853,9 +1880,9 @@ Password: <input type="password" name="password" /></li>
p = UserRegistration(initial={'username': initial_stephane, 'options': initial_options}, auto_id=False)
self.assertHTMLEqual(
p.as_ul(),
- """<li>Username: <input type="text" name="username" value="stephane" maxlength="10" /></li>
-<li>Password: <input type="password" name="password" /></li>
-<li>Options: <select multiple="multiple" name="options">
+ """<li>Username: <input type="text" name="username" value="stephane" maxlength="10" required /></li>
+<li>Password: <input type="password" name="password" required /></li>
+<li>Options: <select multiple="multiple" name="options" required>
<option value="f" selected="selected">foo</option>
<option value="b" selected="selected">bar</option>
<option value="w">whiz</option>
@@ -1925,7 +1952,7 @@ Password: <input type="password" name="password" /></li>
"""
class CustomWidget(TextInput):
def render(self, name, value, attrs=None):
- return format_html(str('<input{} />'), ' id=custom')
+ return format_html(str('<input{} required />'), ' id=custom')
class SampleForm(Form):
name = CharField(widget=CustomWidget)
@@ -1988,23 +2015,23 @@ Password: <input type="password" name="password" /></li>
p = UserRegistration(auto_id=False)
self.assertHTMLEqual(
p.as_ul(),
- """<li>Username: <input type="text" name="username" maxlength="10" />
+ """<li>Username: <input type="text" name="username" maxlength="10" required />
<span class="helptext">e.g., user@example.com</span></li>
-<li>Password: <input type="password" name="password" />
+<li>Password: <input type="password" name="password" required />
<span class="helptext">Wählen Sie mit Bedacht.</span></li>"""
)
self.assertHTMLEqual(
p.as_p(),
- """<p>Username: <input type="text" name="username" maxlength="10" />
+ """<p>Username: <input type="text" name="username" maxlength="10" required />
<span class="helptext">e.g., user@example.com</span></p>
-<p>Password: <input type="password" name="password" />
+<p>Password: <input type="password" name="password" required />
<span class="helptext">Wählen Sie mit Bedacht.</span></p>"""
)
self.assertHTMLEqual(
p.as_table(),
- """<tr><th>Username:</th><td><input type="text" name="username" maxlength="10" /><br />
+ """<tr><th>Username:</th><td><input type="text" name="username" maxlength="10" required /><br />
<span class="helptext">e.g., user@example.com</span></td></tr>
-<tr><th>Password:</th><td><input type="password" name="password" /><br />
+<tr><th>Password:</th><td><input type="password" name="password" required /><br />
<span class="helptext">Wählen Sie mit Bedacht.</span></td></tr>"""
)
@@ -2012,9 +2039,10 @@ Password: <input type="password" name="password" /></li>
p = UserRegistration({'username': 'foo'}, auto_id=False)
self.assertHTMLEqual(
p.as_ul(),
- """<li>Username: <input type="text" name="username" value="foo" maxlength="10" />
+ """<li>Username: <input type="text" name="username" value="foo" maxlength="10" required />
<span class="helptext">e.g., user@example.com</span></li>
-<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" />
+<li><ul class="errorlist"><li>This field is required.</li></ul>
+Password: <input type="password" name="password" required />
<span class="helptext">Wählen Sie mit Bedacht.</span></li>"""
)
@@ -2028,9 +2056,9 @@ Password: <input type="password" name="password" /></li>
p = UserRegistration(auto_id=False)
self.assertHTMLEqual(
p.as_ul(),
- """<li>Username: <input type="text" name="username" maxlength="10" />
+ """<li>Username: <input type="text" name="username" maxlength="10" required />
<span class="helptext">e.g., user@example.com</span></li>
-<li>Password: <input type="password" name="password" />
+<li>Password: <input type="password" name="password" required />
<input type="hidden" name="next" value="/" /></li>"""
)
@@ -2049,17 +2077,17 @@ Password: <input type="password" name="password" /></li>
p = Person(auto_id=False)
self.assertHTMLEqual(
p.as_ul(),
- """<li>First name: <input type="text" name="first_name" /></li>
-<li>Last name: <input type="text" name="last_name" /></li>
-<li>Birthday: <input type="text" name="birthday" /></li>"""
+ """<li>First name: <input type="text" name="first_name" required /></li>
+<li>Last name: <input type="text" name="last_name" required /></li>
+<li>Birthday: <input type="text" name="birthday" required /></li>"""
)
m = Musician(auto_id=False)
self.assertHTMLEqual(
m.as_ul(),
- """<li>First name: <input type="text" name="first_name" /></li>
-<li>Last name: <input type="text" name="last_name" /></li>
-<li>Birthday: <input type="text" name="birthday" /></li>
-<li>Instrument: <input type="text" name="instrument" /></li>"""
+ """<li>First name: <input type="text" name="first_name" required /></li>
+<li>Last name: <input type="text" name="last_name" required /></li>
+<li>Birthday: <input type="text" name="birthday" required /></li>
+<li>Instrument: <input type="text" name="instrument" required /></li>"""
)
# Yes, you can subclass multiple forms. The fields are added in the order in
@@ -2076,11 +2104,11 @@ Password: <input type="password" name="password" /></li>
haircut_type = CharField()
b = Beatle(auto_id=False)
- self.assertHTMLEqual(b.as_ul(), """<li>Instrument: <input type="text" name="instrument" /></li>
-<li>First name: <input type="text" name="first_name" /></li>
-<li>Last name: <input type="text" name="last_name" /></li>
-<li>Birthday: <input type="text" name="birthday" /></li>
-<li>Haircut type: <input type="text" name="haircut_type" /></li>""")
+ self.assertHTMLEqual(b.as_ul(), """<li>Instrument: <input type="text" name="instrument" required /></li>
+<li>First name: <input type="text" name="first_name" required /></li>
+<li>Last name: <input type="text" name="last_name" required /></li>
+<li>Birthday: <input type="text" name="birthday" required /></li>
+<li>Haircut type: <input type="text" name="haircut_type" required /></li>""")
def test_forms_with_prefixes(self):
# Sometimes it's necessary to have multiple forms display on the same HTML page,
@@ -2104,23 +2132,23 @@ Password: <input type="password" name="password" /></li>
self.assertHTMLEqual(
p.as_ul(),
"""<li><label for="id_person1-first_name">First name:</label>
-<input type="text" name="person1-first_name" value="John" id="id_person1-first_name" /></li>
+<input type="text" name="person1-first_name" value="John" id="id_person1-first_name" required /></li>
<li><label for="id_person1-last_name">Last name:</label>
-<input type="text" name="person1-last_name" value="Lennon" id="id_person1-last_name" /></li>
+<input type="text" name="person1-last_name" value="Lennon" id="id_person1-last_name" required /></li>
<li><label for="id_person1-birthday">Birthday:</label>
-<input type="text" name="person1-birthday" value="1940-10-9" id="id_person1-birthday" /></li>"""
+<input type="text" name="person1-birthday" value="1940-10-9" id="id_person1-birthday" required /></li>"""
)
self.assertHTMLEqual(
str(p['first_name']),
- '<input type="text" name="person1-first_name" value="John" id="id_person1-first_name" />'
+ '<input type="text" name="person1-first_name" value="John" id="id_person1-first_name" required />'
)
self.assertHTMLEqual(
str(p['last_name']),
- '<input type="text" name="person1-last_name" value="Lennon" id="id_person1-last_name" />'
+ '<input type="text" name="person1-last_name" value="Lennon" id="id_person1-last_name" required />'
)
self.assertHTMLEqual(
str(p['birthday']),
- '<input type="text" name="person1-birthday" value="1940-10-9" id="id_person1-birthday" />'
+ '<input type="text" name="person1-birthday" value="1940-10-9" id="id_person1-birthday" required />'
)
self.assertEqual(p.errors, {})
self.assertTrue(p.is_valid())
@@ -2195,11 +2223,11 @@ Password: <input type="password" name="password" /></li>
self.assertHTMLEqual(
p.as_ul(),
"""<li><label for="id_foo-prefix-first_name">First name:</label>
-<input type="text" name="foo-prefix-first_name" id="id_foo-prefix-first_name" /></li>
+<input type="text" name="foo-prefix-first_name" id="id_foo-prefix-first_name" required /></li>
<li><label for="id_foo-prefix-last_name">Last name:</label>
-<input type="text" name="foo-prefix-last_name" id="id_foo-prefix-last_name" /></li>
+<input type="text" name="foo-prefix-last_name" id="id_foo-prefix-last_name" required /></li>
<li><label for="id_foo-prefix-birthday">Birthday:</label>
-<input type="text" name="foo-prefix-birthday" id="id_foo-prefix-birthday" /></li>"""
+<input type="text" name="foo-prefix-birthday" id="id_foo-prefix-birthday" required /></li>"""
)
data = {
'foo-prefix-first_name': 'John',
@@ -2232,37 +2260,37 @@ Password: <input type="password" name="password" /></li>
is_cool = NullBooleanField()
p = Person({'name': 'Joe'}, auto_id=False)
- self.assertHTMLEqual(str(p['is_cool']), """<select name="is_cool">
+ self.assertHTMLEqual(str(p['is_cool']), """<select name="is_cool" required>
<option value="1" selected="selected">Unknown</option>
<option value="2">Yes</option>
<option value="3">No</option>
</select>""")
p = Person({'name': 'Joe', 'is_cool': '1'}, auto_id=False)
- self.assertHTMLEqual(str(p['is_cool']), """<select name="is_cool">
+ self.assertHTMLEqual(str(p['is_cool']), """<select name="is_cool" required>
<option value="1" selected="selected">Unknown</option>
<option value="2">Yes</option>
<option value="3">No</option>
</select>""")
p = Person({'name': 'Joe', 'is_cool': '2'}, auto_id=False)
- self.assertHTMLEqual(str(p['is_cool']), """<select name="is_cool">
+ self.assertHTMLEqual(str(p['is_cool']), """<select name="is_cool" required>
<option value="1">Unknown</option>
<option value="2" selected="selected">Yes</option>
<option value="3">No</option>
</select>""")
p = Person({'name': 'Joe', 'is_cool': '3'}, auto_id=False)
- self.assertHTMLEqual(str(p['is_cool']), """<select name="is_cool">
+ self.assertHTMLEqual(str(p['is_cool']), """<select name="is_cool" required>
<option value="1">Unknown</option>
<option value="2">Yes</option>
<option value="3" selected="selected">No</option>
</select>""")
p = Person({'name': 'Joe', 'is_cool': True}, auto_id=False)
- self.assertHTMLEqual(str(p['is_cool']), """<select name="is_cool">
+ self.assertHTMLEqual(str(p['is_cool']), """<select name="is_cool" required>
<option value="1">Unknown</option>
<option value="2" selected="selected">Yes</option>
<option value="3">No</option>
</select>""")
p = Person({'name': 'Joe', 'is_cool': False}, auto_id=False)
- self.assertHTMLEqual(str(p['is_cool']), """<select name="is_cool">
+ self.assertHTMLEqual(str(p['is_cool']), """<select name="is_cool" required>
<option value="1">Unknown</option>
<option value="2">Yes</option>
<option value="3" selected="selected">No</option>
@@ -2275,14 +2303,17 @@ Password: <input type="password" name="password" /></li>
file1 = FileField()
f = FileForm(auto_id=False)
- self.assertHTMLEqual(f.as_table(), '<tr><th>File1:</th><td><input type="file" name="file1" /></td></tr>')
+ self.assertHTMLEqual(
+ f.as_table(),
+ '<tr><th>File1:</th><td><input type="file" name="file1" required /></td></tr>',
+ )
f = FileForm(data={}, files={}, auto_id=False)
self.assertHTMLEqual(
f.as_table(),
'<tr><th>File1:</th><td>'
'<ul class="errorlist"><li>This field is required.</li></ul>'
- '<input type="file" name="file1" /></td></tr>'
+ '<input type="file" name="file1" required /></td></tr>'
)
f = FileForm(data={}, files={'file1': SimpleUploadedFile('name', b'')}, auto_id=False)
@@ -2290,7 +2321,7 @@ Password: <input type="password" name="password" /></li>
f.as_table(),
'<tr><th>File1:</th><td>'
'<ul class="errorlist"><li>The submitted file is empty.</li></ul>'
- '<input type="file" name="file1" /></td></tr>'
+ '<input type="file" name="file1" required /></td></tr>'
)
f = FileForm(data={}, files={'file1': 'something that is not a file'}, auto_id=False)
@@ -2299,16 +2330,22 @@ Password: <input type="password" name="password" /></li>
'<tr><th>File1:</th><td>'
'<ul class="errorlist"><li>No file was submitted. Check the '
'encoding type on the form.</li></ul>'
- '<input type="file" name="file1" /></td></tr>'
+ '<input type="file" name="file1" required /></td></tr>'
)
f = FileForm(data={}, files={'file1': SimpleUploadedFile('name', b'some content')}, auto_id=False)
- self.assertHTMLEqual(f.as_table(), '<tr><th>File1:</th><td><input type="file" name="file1" /></td></tr>')
+ self.assertHTMLEqual(
+ f.as_table(),
+ '<tr><th>File1:</th><td><input type="file" name="file1" required /></td></tr>',
+ )
self.assertTrue(f.is_valid())
file1 = SimpleUploadedFile('我隻氣墊船裝滿晒鱔.txt', 'मेरी मँडराने वाली नाव सर्पमीनों से भरी ह'.encode('utf-8'))
f = FileForm(data={}, files={'file1': file1}, auto_id=False)
- self.assertHTMLEqual(f.as_table(), '<tr><th>File1:</th><td><input type="file" name="file1" /></td></tr>')
+ self.assertHTMLEqual(
+ f.as_table(),
+ '<tr><th>File1:</th><td><input type="file" name="file1" required /></td></tr>',
+ )
def test_basic_processing_in_view(self):
class UserRegistration(Form):
@@ -2334,18 +2371,18 @@ Password: <input type="password" name="password" /></li>
t = Template(
'<form action="" method="post">\n'
- '<table>\n{{ form }}\n</table>\n<input type="submit" />\n</form>'
+ '<table>\n{{ form }}\n</table>\n<input type="submit" required />\n</form>'
)
return t.render(Context({'form': form}))
# Case 1: GET (an empty form, with no errors).)
self.assertHTMLEqual(my_function('GET', {}), """<form action="" method="post">
<table>
-<tr><th>Username:</th><td><input type="text" name="username" maxlength="10" /></td></tr>
-<tr><th>Password1:</th><td><input type="password" name="password1" /></td></tr>
-<tr><th>Password2:</th><td><input type="password" name="password2" /></td></tr>
+<tr><th>Username:</th><td><input type="text" name="username" maxlength="10" required /></td></tr>
+<tr><th>Password1:</th><td><input type="password" name="password1" required /></td></tr>
+<tr><th>Password2:</th><td><input type="password" name="password2" required /></td></tr>
</table>
-<input type="submit" />
+<input type="submit" required />
</form>""")
# Case 2: POST with erroneous data (a redisplayed form, with errors).)
self.assertHTMLEqual(
@@ -2355,11 +2392,11 @@ Password: <input type="password" name="password" /></li>
<tr><td colspan="2"><ul class="errorlist nonfield"><li>Please make sure your passwords match.</li></ul></td></tr>
<tr><th>Username:</th><td><ul class="errorlist">
<li>Ensure this value has at most 10 characters (it has 23).</li></ul>
-<input type="text" name="username" value="this-is-a-long-username" maxlength="10" /></td></tr>
-<tr><th>Password1:</th><td><input type="password" name="password1" /></td></tr>
-<tr><th>Password2:</th><td><input type="password" name="password2" /></td></tr>
+<input type="text" name="username" value="this-is-a-long-username" maxlength="10" required /></td></tr>
+<tr><th>Password1:</th><td><input type="password" name="password1" required /></td></tr>
+<tr><th>Password2:</th><td><input type="password" name="password2" required /></td></tr>
</table>
-<input type="submit" />
+<input type="submit" required />
</form>"""
)
# Case 3: POST with valid data (the success message).)
@@ -2392,23 +2429,23 @@ Password: <input type="password" name="password" /></li>
{{ form.username.errors.as_ul }}<p><label>Your username: {{ form.username }}</label></p>
{{ form.password1.errors.as_ul }}<p><label>Password: {{ form.password1 }}</label></p>
{{ form.password2.errors.as_ul }}<p><label>Password (again): {{ form.password2 }}</label></p>
-<input type="submit" />
+<input type="submit" required />
</form>''')
self.assertHTMLEqual(t.render(Context({'form': UserRegistration(auto_id=False)})), """<form action="">
-<p><label>Your username: <input type="text" name="username" maxlength="10" /></label></p>
-<p><label>Password: <input type="password" name="password1" /></label></p>
-<p><label>Password (again): <input type="password" name="password2" /></label></p>
-<input type="submit" />
+<p><label>Your username: <input type="text" name="username" maxlength="10" required /></label></p>
+<p><label>Password: <input type="password" name="password1" required /></label></p>
+<p><label>Password (again): <input type="password" name="password2" required /></label></p>
+<input type="submit" required />
</form>""")
self.assertHTMLEqual(
t.render(Context({'form': UserRegistration({'username': 'django'}, auto_id=False)})),
"""<form action="">
-<p><label>Your username: <input type="text" name="username" value="django" maxlength="10" /></label></p>
+<p><label>Your username: <input type="text" name="username" value="django" maxlength="10" required /></label></p>
<ul class="errorlist"><li>This field is required.</li></ul><p>
-<label>Password: <input type="password" name="password1" /></label></p>
+<label>Password: <input type="password" name="password1" required /></label></p>
<ul class="errorlist"><li>This field is required.</li></ul>
-<p><label>Password (again): <input type="password" name="password2" /></label></p>
-<input type="submit" />
+<p><label>Password (again): <input type="password" name="password2" required /></label></p>
+<input type="submit" required />
</form>"""
)
@@ -2420,13 +2457,13 @@ Password: <input type="password" name="password" /></li>
<p><label>{{ form.username.label }}: {{ form.username }}</label></p>
<p><label>{{ form.password1.label }}: {{ form.password1 }}</label></p>
<p><label>{{ form.password2.label }}: {{ form.password2 }}</label></p>
-<input type="submit" />
+<input type="submit" required />
</form>''')
self.assertHTMLEqual(t.render(Context({'form': UserRegistration(auto_id=False)})), """<form action="">
-<p><label>Username: <input type="text" name="username" maxlength="10" /></label></p>
-<p><label>Password1: <input type="password" name="password1" /></label></p>
-<p><label>Password2: <input type="password" name="password2" /></label></p>
-<input type="submit" />
+<p><label>Username: <input type="text" name="username" maxlength="10" required /></label></p>
+<p><label>Password1: <input type="password" name="password1" required /></label></p>
+<p><label>Password2: <input type="password" name="password2" required /></label></p>
+<input type="submit" required />
</form>""")
# User form.[field].label_tag to output a field's label with a <label> tag
@@ -2437,19 +2474,22 @@ Password: <input type="password" name="password" /></li>
<p>{{ form.username.label_tag }} {{ form.username }}</p>
<p>{{ form.password1.label_tag }} {{ form.password1 }}</p>
<p>{{ form.password2.label_tag }} {{ form.password2 }}</p>
-<input type="submit" />
+<input type="submit" required />
</form>''')
self.assertHTMLEqual(t.render(Context({'form': UserRegistration(auto_id=False)})), """<form action="">
-<p>Username: <input type="text" name="username" maxlength="10" /></p>
-<p>Password1: <input type="password" name="password1" /></p>
-<p>Password2: <input type="password" name="password2" /></p>
-<input type="submit" />
+<p>Username: <input type="text" name="username" maxlength="10" required /></p>
+<p>Password1: <input type="password" name="password1" required /></p>
+<p>Password2: <input type="password" name="password2" required /></p>
+<input type="submit" required />
</form>""")
self.assertHTMLEqual(t.render(Context({'form': UserRegistration(auto_id='id_%s')})), """<form action="">
-<p><label for="id_username">Username:</label> <input id="id_username" type="text" name="username" maxlength="10" /></p>
-<p><label for="id_password1">Password1:</label> <input type="password" name="password1" id="id_password1" /></p>
-<p><label for="id_password2">Password2:</label> <input type="password" name="password2" id="id_password2" /></p>
-<input type="submit" />
+<p><label for="id_username">Username:</label>
+<input id="id_username" type="text" name="username" maxlength="10" required /></p>
+<p><label for="id_password1">Password1:</label>
+<input type="password" name="password1" id="id_password1" required /></p>
+<p><label for="id_password2">Password2:</label>
+<input type="password" name="password2" id="id_password2" required /></p>
+<input type="submit" required />
</form>""")
# User form.[field].help_text to output a field's help text. If the given field
@@ -2458,16 +2498,16 @@ Password: <input type="password" name="password" /></li>
<p>{{ form.username.label_tag }} {{ form.username }}<br />{{ form.username.help_text }}</p>
<p>{{ form.password1.label_tag }} {{ form.password1 }}</p>
<p>{{ form.password2.label_tag }} {{ form.password2 }}</p>
-<input type="submit" />
+<input type="submit" required />
</form>''')
self.assertHTMLEqual(
t.render(Context({'form': UserRegistration(auto_id=False)})),
"""<form action="">
-<p>Username: <input type="text" name="username" maxlength="10" /><br />
+<p>Username: <input type="text" name="username" maxlength="10" required /><br />
Good luck picking a username that doesn&#39;t already exist.</p>
-<p>Password1: <input type="password" name="password1" /></p>
-<p>Password2: <input type="password" name="password2" /></p>
-<input type="submit" />
+<p>Password1: <input type="password" name="password1" required /></p>
+<p>Password2: <input type="password" name="password2" required /></p>
+<input type="submit" required />
</form>"""
)
self.assertEqual(
@@ -2483,17 +2523,17 @@ Good luck picking a username that doesn&#39;t already exist.</p>
{{ form.username.errors.as_ul }}<p><label>Your username: {{ form.username }}</label></p>
{{ form.password1.errors.as_ul }}<p><label>Password: {{ form.password1 }}</label></p>
{{ form.password2.errors.as_ul }}<p><label>Password (again): {{ form.password2 }}</label></p>
-<input type="submit" />
+<input type="submit" required />
</form>''')
self.assertHTMLEqual(
t.render(Context({
'form': UserRegistration({'username': 'django', 'password1': 'foo', 'password2': 'bar'}, auto_id=False)
})),
"""<form action="">
-<p><label>Your username: <input type="text" name="username" value="django" maxlength="10" /></label></p>
-<p><label>Password: <input type="password" name="password1" /></label></p>
-<p><label>Password (again): <input type="password" name="password2" /></label></p>
-<input type="submit" />
+<p><label>Your username: <input type="text" name="username" value="django" maxlength="10" required /></label></p>
+<p><label>Password: <input type="password" name="password1" required /></label></p>
+<p><label>Password (again): <input type="password" name="password2" required /></label></p>
+<input type="submit" required />
</form>"""
)
t = Template('''<form action="">
@@ -2501,7 +2541,7 @@ Good luck picking a username that doesn&#39;t already exist.</p>
{{ form.username.errors.as_ul }}<p><label>Your username: {{ form.username }}</label></p>
{{ form.password1.errors.as_ul }}<p><label>Password: {{ form.password1 }}</label></p>
{{ form.password2.errors.as_ul }}<p><label>Password (again): {{ form.password2 }}</label></p>
-<input type="submit" />
+<input type="submit" required />
</form>''')
self.assertHTMLEqual(
t.render(Context({
@@ -2509,10 +2549,10 @@ Good luck picking a username that doesn&#39;t already exist.</p>
})),
"""<form action="">
<ul class="errorlist nonfield"><li>Please make sure your passwords match.</li></ul>
-<p><label>Your username: <input type="text" name="username" value="django" maxlength="10" /></label></p>
-<p><label>Password: <input type="password" name="password1" /></label></p>
-<p><label>Password (again): <input type="password" name="password2" /></label></p>
-<input type="submit" />
+<p><label>Your username: <input type="text" name="username" value="django" maxlength="10" required /></label></p>
+<p><label>Password: <input type="password" name="password1" required /></label></p>
+<p><label>Password (again): <input type="password" name="password2" required /></label></p>
+<input type="submit" required />
</form>"""
)
@@ -2579,7 +2619,7 @@ Good luck picking a username that doesn&#39;t already exist.</p>
self.assertHTMLEqual(
MyForm().as_table(),
'<tr><th><label for="id_field1">Field1:</label></th>'
- '<td><input id="id_field1" type="text" name="field1" maxlength="50" />'
+ '<td><input id="id_field1" type="text" name="field1" maxlength="50" required />'
'<input type="hidden" name="initial-field1" id="initial-id_field1" /></td></tr>'
)
@@ -2597,24 +2637,25 @@ Good luck picking a username that doesn&#39;t already exist.</p>
self.assertHTMLEqual(
p.as_ul(),
"""<li class="required error"><ul class="errorlist"><li>This field is required.</li></ul>
-<label class="required" for="id_name">Name:</label> <input type="text" name="name" id="id_name" /></li>
-<li class="required"><label class="required" for="id_is_cool">Is cool:</label> <select name="is_cool" id="id_is_cool">
+<label class="required" for="id_name">Name:</label> <input type="text" name="name" id="id_name" required /></li>
+<li class="required"><label class="required" for="id_is_cool">Is cool:</label>
+<select name="is_cool" id="id_is_cool" required>
<option value="1" selected="selected">Unknown</option>
<option value="2">Yes</option>
<option value="3">No</option>
</select></li>
<li><label for="id_email">Email:</label> <input type="email" name="email" id="id_email" /></li>
<li class="required error"><ul class="errorlist"><li>This field is required.</li></ul>
-<label class="required" for="id_age">Age:</label> <input type="number" name="age" id="id_age" /></li>"""
+<label class="required" for="id_age">Age:</label> <input type="number" name="age" id="id_age" required /></li>"""
)
self.assertHTMLEqual(
p.as_p(),
"""<ul class="errorlist"><li>This field is required.</li></ul>
<p class="required error"><label class="required" for="id_name">Name:</label>
-<input type="text" name="name" id="id_name" /></p>
+<input type="text" name="name" id="id_name" required /></p>
<p class="required"><label class="required" for="id_is_cool">Is cool:</label>
-<select name="is_cool" id="id_is_cool">
+<select name="is_cool" id="id_is_cool" required>
<option value="1" selected="selected">Unknown</option>
<option value="2">Yes</option>
<option value="3">No</option>
@@ -2622,7 +2663,7 @@ Good luck picking a username that doesn&#39;t already exist.</p>
<p><label for="id_email">Email:</label> <input type="email" name="email" id="id_email" /></p>
<ul class="errorlist"><li>This field is required.</li></ul>
<p class="required error"><label class="required" for="id_age">Age:</label>
-<input type="number" name="age" id="id_age" /></p>"""
+<input type="number" name="age" id="id_age" required /></p>"""
)
self.assertHTMLEqual(
@@ -2630,9 +2671,9 @@ Good luck picking a username that doesn&#39;t already exist.</p>
"""<tr class="required error">
<th><label class="required" for="id_name">Name:</label></th>
<td><ul class="errorlist"><li>This field is required.</li></ul>
-<input type="text" name="name" id="id_name" /></td></tr>
+<input type="text" name="name" id="id_name" required /></td></tr>
<tr class="required"><th><label class="required" for="id_is_cool">Is cool:</label></th>
-<td><select name="is_cool" id="id_is_cool">
+<td><select name="is_cool" id="id_is_cool" required>
<option value="1" selected="selected">Unknown</option>
<option value="2">Yes</option>
<option value="3">No</option>
@@ -2641,7 +2682,7 @@ Good luck picking a username that doesn&#39;t already exist.</p>
<input type="email" name="email" id="id_email" /></td></tr>
<tr class="required error"><th><label class="required" for="id_age">Age:</label></th>
<td><ul class="errorlist"><li>This field is required.</li></ul>
-<input type="number" name="age" id="id_age" /></td></tr>"""
+<input type="number" name="age" id="id_age" required /></td></tr>"""
)
def test_label_has_required_css_class(self):
@@ -3007,7 +3048,7 @@ Good luck picking a username that doesn&#39;t already exist.</p>
form = SomeForm()
self.assertHTMLEqual(
form.as_p(),
- '<p><input id="id_custom" name="custom" type="text" /> custom'
+ '<p><input id="id_custom" name="custom" type="text" required /> custom'
'<input id="id_hidden1" name="hidden1" type="hidden" />'
'<input id="id_hidden2" name="hidden2" type="hidden" /></p>'
)
@@ -3026,7 +3067,7 @@ Good luck picking a username that doesn&#39;t already exist.</p>
return self._html_output(
normal_row='<p%(html_class_attr)s>%(field)s %(field_name)s</p>',
error_row='%s',
- row_ender='<hr/><hr/>',
+ row_ender='<hr /><hr />',
help_text_html=' %s',
errors_on_separate_row=True
)
@@ -3034,9 +3075,9 @@ Good luck picking a username that doesn&#39;t already exist.</p>
form = SomeForm()
self.assertHTMLEqual(
form.as_p(),
- '<p><input id="id_custom" name="custom" type="text" /> custom</p>\n'
+ '<p><input id="id_custom" name="custom" type="text" required /> custom</p>\n'
'<input id="id_hidden1" name="hidden1" type="hidden" />'
- '<input id="id_hidden2" name="hidden2" type="hidden" /><hr/><hr/>'
+ '<input id="id_hidden2" name="hidden2" type="hidden" /><hr /><hr />'
)
def test_error_dict(self):
@@ -3156,14 +3197,14 @@ Good luck picking a username that doesn&#39;t already exist.</p>
"""<li><ul class="errorlist nonfield">
<li>(Hidden field last_name) This field is required.</li></ul></li><li>
<label for="id_first_name">First name:</label>
-<input id="id_first_name" name="first_name" type="text" value="John" />
+<input id="id_first_name" name="first_name" type="text" value="John" required />
<input id="id_last_name" name="last_name" type="hidden" /></li>"""
)
self.assertHTMLEqual(
p.as_p(),
"""<ul class="errorlist nonfield"><li>(Hidden field last_name) This field is required.</li></ul>
<p><label for="id_first_name">First name:</label>
-<input id="id_first_name" name="first_name" type="text" value="John" />
+<input id="id_first_name" name="first_name" type="text" value="John" required />
<input id="id_last_name" name="last_name" type="hidden" /></p>"""
)
self.assertHTMLEqual(
@@ -3171,7 +3212,7 @@ Good luck picking a username that doesn&#39;t already exist.</p>
"""<tr><td colspan="2"><ul class="errorlist nonfield">
<li>(Hidden field last_name) This field is required.</li></ul></td></tr>
<tr><th><label for="id_first_name">First name:</label></th><td>
-<input id="id_first_name" name="first_name" type="text" value="John" />
+<input id="id_first_name" name="first_name" type="text" value="John" required />
<input id="id_last_name" name="last_name" type="hidden" /></td></tr>"""
)
@@ -3193,9 +3234,9 @@ Good luck picking a username that doesn&#39;t already exist.</p>
"""<li>
<ul class="errorlist nonfield"><li>Generic validation error</li></ul></li>
<li><label for="id_first_name">First name:</label>
-<input id="id_first_name" name="first_name" type="text" value="John" /></li>
+<input id="id_first_name" name="first_name" type="text" value="John" required /></li>
<li><label for="id_last_name">Last name:</label>
-<input id="id_last_name" name="last_name" type="text" value="Lennon" /></li>"""
+<input id="id_last_name" name="last_name" type="text" value="Lennon" required /></li>"""
)
self.assertHTMLEqual(
p.non_field_errors().as_text(),
@@ -3205,17 +3246,17 @@ Good luck picking a username that doesn&#39;t already exist.</p>
p.as_p(),
"""<ul class="errorlist nonfield"><li>Generic validation error</li></ul>
<p><label for="id_first_name">First name:</label>
-<input id="id_first_name" name="first_name" type="text" value="John" /></p>
+<input id="id_first_name" name="first_name" type="text" value="John" required /></p>
<p><label for="id_last_name">Last name:</label>
-<input id="id_last_name" name="last_name" type="text" value="Lennon" /></p>"""
+<input id="id_last_name" name="last_name" type="text" value="Lennon" required /></p>"""
)
self.assertHTMLEqual(
p.as_table(),
"""<tr><td colspan="2"><ul class="errorlist nonfield"><li>Generic validation error</li></ul></td></tr>
<tr><th><label for="id_first_name">First name:</label></th><td>
-<input id="id_first_name" name="first_name" type="text" value="John" /></td></tr>
+<input id="id_first_name" name="first_name" type="text" value="John" required /></td></tr>
<tr><th><label for="id_last_name">Last name:</label></th><td>
-<input id="id_last_name" name="last_name" type="text" value="Lennon" /></td></tr>"""
+<input id="id_last_name" name="last_name" type="text" value="Lennon" required /></td></tr>"""
)
def test_errorlist_override(self):
@@ -3239,9 +3280,9 @@ Good luck picking a username that doesn&#39;t already exist.</p>
f = CommentForm(data, auto_id=False, error_class=DivErrorList)
self.assertHTMLEqual(f.as_p(), """<p>Name: <input type="text" name="name" maxlength="50" /></p>
<div class="errorlist"><div class="error">Enter a valid email address.</div></div>
-<p>Email: <input type="email" name="email" value="invalid" /></p>
+<p>Email: <input type="email" name="email" value="invalid" required /></p>
<div class="errorlist"><div class="error">This field is required.</div></div>
-<p>Comment: <input type="text" name="comment" /></p>""")
+<p>Comment: <input type="text" name="comment" required /></p>""")
def test_baseform_repr(self):
"""
@@ -3341,3 +3382,95 @@ Good luck picking a username that doesn&#39;t already exist.</p>
self.assertEqual(force_text(form), form.__html__())
self.assertTrue(hasattr(form['username'], '__html__'))
self.assertEqual(force_text(form['username']), form['username'].__html__())
+
+ def test_use_required_attribute_true(self):
+ class MyForm(Form):
+ use_required_attribute = True
+ f1 = CharField(max_length=30)
+ f2 = CharField(max_length=30, required=False)
+ f3 = CharField(widget=Textarea)
+ f4 = ChoiceField(choices=[('P', 'Python'), ('J', 'Java')])
+
+ form = MyForm()
+ self.assertHTMLEqual(
+ form.as_p(),
+ '<p><label for="id_f1">F1:</label> <input id="id_f1" maxlength="30" name="f1" type="text" required /></p>'
+ '<p><label for="id_f2">F2:</label> <input id="id_f2" maxlength="30" name="f2" type="text" /></p>'
+ '<p><label for="id_f3">F3:</label> <textarea cols="40" id="id_f3" name="f3" rows="10" required>'
+ '</textarea></p>'
+ '<p><label for="id_f4">F4:</label> <select id="id_f4" name="f4" required>'
+ '<option value="P">Python</option>'
+ '<option value="J">Java</option>'
+ '</select></p>',
+ )
+ self.assertHTMLEqual(
+ form.as_ul(),
+ '<li><label for="id_f1">F1:</label> '
+ '<input id="id_f1" maxlength="30" name="f1" type="text" required /></li>'
+ '<li><label for="id_f2">F2:</label> <input id="id_f2" maxlength="30" name="f2" type="text" /></li>'
+ '<li><label for="id_f3">F3:</label> <textarea cols="40" id="id_f3" name="f3" rows="10" required>'
+ '</textarea></li>'
+ '<li><label for="id_f4">F4:</label> <select id="id_f4" name="f4" required>'
+ '<option value="P">Python</option>'
+ '<option value="J">Java</option>'
+ '</select></li>',
+ )
+ self.assertHTMLEqual(
+ form.as_table(),
+ '<tr><th><label for="id_f1">F1:</label></th>'
+ '<td><input id="id_f1" maxlength="30" name="f1" type="text" required /></td></tr>'
+ '<tr><th><label for="id_f2">F2:</label></th>'
+ '<td><input id="id_f2" maxlength="30" name="f2" type="text" /></td></tr>'
+ '<tr><th><label for="id_f3">F3:</label></th>'
+ '<td><textarea cols="40" id="id_f3" name="f3" rows="10" required>'
+ '</textarea></td></tr>'
+ '<tr><th><label for="id_f4">F4:</label></th><td><select id="id_f4" name="f4" required>'
+ '<option value="P">Python</option>'
+ '<option value="J">Java</option>'
+ '</select></td></tr>',
+ )
+
+ def test_use_required_attribute_false(self):
+ class MyForm(Form):
+ use_required_attribute = False
+ f1 = CharField(max_length=30)
+ f2 = CharField(max_length=30, required=False)
+ f3 = CharField(widget=Textarea)
+ f4 = ChoiceField(choices=[('P', 'Python'), ('J', 'Java')])
+
+ form = MyForm()
+ self.assertHTMLEqual(
+ form.as_p(),
+ '<p><label for="id_f1">F1:</label> <input id="id_f1" maxlength="30" name="f1" type="text" /></p>'
+ '<p><label for="id_f2">F2:</label> <input id="id_f2" maxlength="30" name="f2" type="text" /></p>'
+ '<p><label for="id_f3">F3:</label> <textarea cols="40" id="id_f3" name="f3" rows="10">'
+ '</textarea></p>'
+ '<p><label for="id_f4">F4:</label> <select id="id_f4" name="f4">'
+ '<option value="P">Python</option>'
+ '<option value="J">Java</option>'
+ '</select></p>',
+ )
+ self.assertHTMLEqual(
+ form.as_ul(),
+ '<li><label for="id_f1">F1:</label> <input id="id_f1" maxlength="30" name="f1" type="text" /></li>'
+ '<li><label for="id_f2">F2:</label> <input id="id_f2" maxlength="30" name="f2" type="text" /></li>'
+ '<li><label for="id_f3">F3:</label> <textarea cols="40" id="id_f3" name="f3" rows="10">'
+ '</textarea></li>'
+ '<li><label for="id_f4">F4:</label> <select id="id_f4" name="f4">'
+ '<option value="P">Python</option>'
+ '<option value="J">Java</option>'
+ '</select></li>',
+ )
+ self.assertHTMLEqual(
+ form.as_table(),
+ '<tr><th><label for="id_f1">F1:</label></th>'
+ '<td><input id="id_f1" maxlength="30" name="f1" type="text" /></td></tr>'
+ '<tr><th><label for="id_f2">F2:</label></th>'
+ '<td><input id="id_f2" maxlength="30" name="f2" type="text" /></td></tr>'
+ '<tr><th><label for="id_f3">F3:</label></th><td><textarea cols="40" id="id_f3" name="f3" rows="10">'
+ '</textarea></td></tr>'
+ '<tr><th><label for="id_f4">F4:</label></th><td><select id="id_f4" name="f4">'
+ '<option value="P">Python</option>'
+ '<option value="J">Java</option>'
+ '</select></td></tr>',
+ )
diff --git a/tests/forms_tests/tests/test_regressions.py b/tests/forms_tests/tests/test_regressions.py
index 10e5b3f983..e183694234 100644
--- a/tests/forms_tests/tests/test_regressions.py
+++ b/tests/forms_tests/tests/test_regressions.py
@@ -24,8 +24,8 @@ class FormsRegressionsTestCase(TestCase):
self.assertHTMLEqual(
TestForm(auto_id=False).as_p(),
- '<p>F1: <input type="text" class="special" name="f1" maxlength="10" /></p>\n'
- '<p>F2: <input type="text" class="special" name="f2" /></p>'
+ '<p>F1: <input type="text" class="special" name="f1" maxlength="10" required /></p>\n'
+ '<p>F2: <input type="text" class="special" name="f2" required /></p>'
)
def test_regression_3600(self):
@@ -39,7 +39,7 @@ class FormsRegressionsTestCase(TestCase):
self.assertHTMLEqual(
f.as_p(),
'<p><label for="id_username">username:</label>'
- '<input id="id_username" type="text" name="username" maxlength="10" /></p>'
+ '<input id="id_username" type="text" name="username" maxlength="10" required /></p>'
)
# Translations are done at rendering time, so multi-lingual apps can define forms)
@@ -47,13 +47,13 @@ class FormsRegressionsTestCase(TestCase):
self.assertHTMLEqual(
f.as_p(),
'<p><label for="id_username">Benutzername:</label>'
- '<input id="id_username" type="text" name="username" maxlength="10" /></p>'
+ '<input id="id_username" type="text" name="username" maxlength="10" required /></p>'
)
with translation.override('pl'):
self.assertHTMLEqual(
f.as_p(),
'<p><label for="id_username">u\u017cytkownik:</label>'
- '<input id="id_username" type="text" name="username" maxlength="10" /></p>'
+ '<input id="id_username" type="text" name="username" maxlength="10" required /></p>'
)
def test_regression_5216(self):
@@ -82,12 +82,12 @@ class FormsRegressionsTestCase(TestCase):
'<p><label for="id_somechoice_0">\xc5\xf8\xdf:</label>'
'<ul id="id_somechoice">\n'
'<li><label for="id_somechoice_0">'
- '<input type="radio" id="id_somechoice_0" value="\xc5" name="somechoice" /> '
+ '<input type="radio" id="id_somechoice_0" value="\xc5" name="somechoice" required /> '
'En tied\xe4</label></li>\n'
'<li><label for="id_somechoice_1">'
- '<input type="radio" id="id_somechoice_1" value="\xf8" name="somechoice" /> '
+ '<input type="radio" id="id_somechoice_1" value="\xf8" name="somechoice" required /> '
'Mies</label></li>\n<li><label for="id_somechoice_2">'
- '<input type="radio" id="id_somechoice_2" value="\xdf" name="somechoice" /> '
+ '<input type="radio" id="id_somechoice_2" value="\xdf" name="somechoice" required /> '
'Nainen</label></li>\n</ul></p>'
)
@@ -101,12 +101,12 @@ class FormsRegressionsTestCase(TestCase):
'\u043d\u043e\u0435 \u043f\u043e\u043b\u0435.</li></ul>\n'
'<p><label for="id_somechoice_0">\xc5\xf8\xdf:</label>'
' <ul id="id_somechoice">\n<li><label for="id_somechoice_0">'
- '<input type="radio" id="id_somechoice_0" value="\xc5" name="somechoice" /> '
+ '<input type="radio" id="id_somechoice_0" value="\xc5" name="somechoice" required /> '
'En tied\xe4</label></li>\n'
'<li><label for="id_somechoice_1">'
- '<input type="radio" id="id_somechoice_1" value="\xf8" name="somechoice" /> '
+ '<input type="radio" id="id_somechoice_1" value="\xf8" name="somechoice" required /> '
'Mies</label></li>\n<li><label for="id_somechoice_2">'
- '<input type="radio" id="id_somechoice_2" value="\xdf" name="somechoice" /> '
+ '<input type="radio" id="id_somechoice_2" value="\xdf" name="somechoice" required /> '
'Nainen</label></li>\n</ul></p>'
)
diff --git a/tests/forms_tests/tests/tests.py b/tests/forms_tests/tests/tests.py
index f1bd66fc6b..bc4aebd5c4 100644
--- a/tests/forms_tests/tests/tests.py
+++ b/tests/forms_tests/tests/tests.py
@@ -109,24 +109,24 @@ class ModelFormCallableModelDefault(TestCase):
ChoiceOptionModel.objects.create(id=3, name='option 3')
self.assertHTMLEqual(
ChoiceFieldForm().as_p(),
- """<p><label for="id_choice">Choice:</label> <select name="choice" id="id_choice">
+ """<p><label for="id_choice">Choice:</label> <select name="choice" id="id_choice" required>
<option value="1" selected="selected">ChoiceOption 1</option>
<option value="2">ChoiceOption 2</option>
<option value="3">ChoiceOption 3</option>
</select><input type="hidden" name="initial-choice" value="1" id="initial-id_choice" /></p>
-<p><label for="id_choice_int">Choice int:</label> <select name="choice_int" id="id_choice_int">
+<p><label for="id_choice_int">Choice int:</label> <select name="choice_int" id="id_choice_int" required>
<option value="1" selected="selected">ChoiceOption 1</option>
<option value="2">ChoiceOption 2</option>
<option value="3">ChoiceOption 3</option>
</select><input type="hidden" name="initial-choice_int" value="1" id="initial-id_choice_int" /></p>
<p><label for="id_multi_choice">Multi choice:</label>
-<select multiple="multiple" name="multi_choice" id="id_multi_choice">
+<select multiple="multiple" name="multi_choice" id="id_multi_choice" required>
<option value="1" selected="selected">ChoiceOption 1</option>
<option value="2">ChoiceOption 2</option>
<option value="3">ChoiceOption 3</option>
</select><input type="hidden" name="initial-multi_choice" value="1" id="initial-id_multi_choice_0" /></p>
<p><label for="id_multi_choice_int">Multi choice int:</label>
-<select multiple="multiple" name="multi_choice_int" id="id_multi_choice_int">
+<select multiple="multiple" name="multi_choice_int" id="id_multi_choice_int" required>
<option value="1" selected="selected">ChoiceOption 1</option>
<option value="2">ChoiceOption 2</option>
<option value="3">ChoiceOption 3</option>
@@ -145,25 +145,25 @@ class ModelFormCallableModelDefault(TestCase):
'multi_choice': [obj2, obj3],
'multi_choice_int': ChoiceOptionModel.objects.exclude(name="default"),
}).as_p(),
- """<p><label for="id_choice">Choice:</label> <select name="choice" id="id_choice">
+ """<p><label for="id_choice">Choice:</label> <select name="choice" id="id_choice" required>
<option value="1">ChoiceOption 1</option>
<option value="2" selected="selected">ChoiceOption 2</option>
<option value="3">ChoiceOption 3</option>
</select><input type="hidden" name="initial-choice" value="2" id="initial-id_choice" /></p>
-<p><label for="id_choice_int">Choice int:</label> <select name="choice_int" id="id_choice_int">
+<p><label for="id_choice_int">Choice int:</label> <select name="choice_int" id="id_choice_int" required>
<option value="1">ChoiceOption 1</option>
<option value="2" selected="selected">ChoiceOption 2</option>
<option value="3">ChoiceOption 3</option>
</select><input type="hidden" name="initial-choice_int" value="2" id="initial-id_choice_int" /></p>
<p><label for="id_multi_choice">Multi choice:</label>
-<select multiple="multiple" name="multi_choice" id="id_multi_choice">
+<select multiple="multiple" name="multi_choice" id="id_multi_choice" required>
<option value="1">ChoiceOption 1</option>
<option value="2" selected="selected">ChoiceOption 2</option>
<option value="3" selected="selected">ChoiceOption 3</option>
</select><input type="hidden" name="initial-multi_choice" value="2" id="initial-id_multi_choice_0" />
<input type="hidden" name="initial-multi_choice" value="3" id="initial-id_multi_choice_1" /></p>
<p><label for="id_multi_choice_int">Multi choice int:</label>
-<select multiple="multiple" name="multi_choice_int" id="id_multi_choice_int">
+<select multiple="multiple" name="multi_choice_int" id="id_multi_choice_int" required>
<option value="1">ChoiceOption 1</option>
<option value="2" selected="selected">ChoiceOption 2</option>
<option value="3" selected="selected">ChoiceOption 3</option>
@@ -308,7 +308,7 @@ class EmptyLabelTestCase(TestCase):
f = EmptyCharLabelChoiceForm()
self.assertHTMLEqual(
f.as_p(),
- """<p><label for="id_name">Name:</label> <input id="id_name" maxlength="10" name="name" type="text" /></p>
+ """<p><label for="id_name">Name:</label> <input id="id_name" maxlength="10" name="name" type="text" required /></p>
<p><label for="id_choice">Choice:</label> <select id="id_choice" name="choice">
<option value="" selected="selected">No Preference</option>
<option value="f">Foo</option>
@@ -320,7 +320,7 @@ class EmptyLabelTestCase(TestCase):
f = EmptyCharLabelNoneChoiceForm()
self.assertHTMLEqual(
f.as_p(),
- """<p><label for="id_name">Name:</label> <input id="id_name" maxlength="10" name="name" type="text" /></p>
+ """<p><label for="id_name">Name:</label> <input id="id_name" maxlength="10" name="name" type="text" required /></p>
<p><label for="id_choice_string_w_none">Choice string w none:</label>
<select id="id_choice_string_w_none" name="choice_string_w_none">
<option value="" selected="selected">No Preference</option>
@@ -350,7 +350,7 @@ class EmptyLabelTestCase(TestCase):
f = EmptyIntegerLabelChoiceForm()
self.assertHTMLEqual(
f.as_p(),
- """<p><label for="id_name">Name:</label> <input id="id_name" maxlength="10" name="name" type="text" /></p>
+ """<p><label for="id_name">Name:</label> <input id="id_name" maxlength="10" name="name" type="text" required /></p>
<p><label for="id_choice_integer">Choice integer:</label>
<select id="id_choice_integer" name="choice_integer">
<option value="" selected="selected">No Preference</option>
@@ -370,7 +370,7 @@ class EmptyLabelTestCase(TestCase):
self.assertHTMLEqual(
f.as_p(),
"""<p><label for="id_name">Name:</label>
-<input id="id_name" maxlength="10" name="name" type="text" value="none-test"/></p>
+<input id="id_name" maxlength="10" name="name" type="text" value="none-test" required /></p>
<p><label for="id_choice_integer">Choice integer:</label>
<select id="id_choice_integer" name="choice_integer">
<option value="" selected="selected">No Preference</option>
@@ -384,7 +384,7 @@ class EmptyLabelTestCase(TestCase):
self.assertHTMLEqual(
f.as_p(),
"""<p><label for="id_name">Name:</label>
-<input id="id_name" maxlength="10" name="name" type="text" value="foo-test"/></p>
+<input id="id_name" maxlength="10" name="name" type="text" value="foo-test" required /></p>
<p><label for="id_choice_integer">Choice integer:</label>
<select id="id_choice_integer" name="choice_integer">
<option value="">No Preference</option>
diff --git a/tests/i18n/tests.py b/tests/i18n/tests.py
index e860702313..140e2da187 100644
--- a/tests/i18n/tests.py
+++ b/tests/i18n/tests.py
@@ -1108,20 +1108,22 @@ class FormattingTests(SimpleTestCase):
self.assertHTMLEqual(
form6.as_ul(),
'<li><label for="id_name">Name:</label>'
- '<input id="id_name" type="text" name="name" value="acme" maxlength="50" /></li>'
+ '<input id="id_name" type="text" name="name" value="acme" maxlength="50" required /></li>'
'<li><label for="id_date_added">Date added:</label>'
- '<input type="text" name="date_added" value="31.12.2009 06:00:00" id="id_date_added" /></li>'
+ '<input type="text" name="date_added" value="31.12.2009 06:00:00" id="id_date_added" required /></li>'
'<li><label for="id_cents_paid">Cents paid:</label>'
- '<input type="text" name="cents_paid" value="59,47" id="id_cents_paid" /></li>'
+ '<input type="text" name="cents_paid" value="59,47" id="id_cents_paid" required /></li>'
'<li><label for="id_products_delivered">Products delivered:</label>'
- '<input type="text" name="products_delivered" value="12000" id="id_products_delivered" /></li>'
+ '<input type="text" name="products_delivered" value="12000" id="id_products_delivered" required />'
+ '</li>'
)
self.assertEqual(localize_input(datetime.datetime(2009, 12, 31, 6, 0, 0)), '31.12.2009 06:00:00')
self.assertEqual(datetime.datetime(2009, 12, 31, 6, 0, 0), form6.cleaned_data['date_added'])
with self.settings(USE_THOUSAND_SEPARATOR=True):
# Checking for the localized "products_delivered" field
self.assertInHTML(
- '<input type="text" name="products_delivered" value="12.000" id="id_products_delivered" />',
+ '<input type="text" name="products_delivered" '
+ 'value="12.000" id="id_products_delivered" required />',
form6.as_ul()
)
@@ -1247,13 +1249,13 @@ class FormattingTests(SimpleTestCase):
self.assertHTMLEqual(
template.render(context),
- '<input id="id_date_added" name="date_added" type="text" value="31.12.2009 06:00:00" />;'
- '<input id="id_cents_paid" name="cents_paid" type="text" value="59,47" />'
+ '<input id="id_date_added" name="date_added" type="text" value="31.12.2009 06:00:00" required />;'
+ '<input id="id_cents_paid" name="cents_paid" type="text" value="59,47" required />'
)
self.assertHTMLEqual(
template_as_text.render(context),
- '<input id="id_date_added" name="date_added" type="text" value="31.12.2009 06:00:00" />;'
- ' <input id="id_cents_paid" name="cents_paid" type="text" value="59,47" />'
+ '<input id="id_date_added" name="date_added" type="text" value="31.12.2009 06:00:00" required />;'
+ ' <input id="id_cents_paid" name="cents_paid" type="text" value="59,47" required />'
)
self.assertHTMLEqual(
template_as_hidden.render(context),
diff --git a/tests/model_forms/tests.py b/tests/model_forms/tests.py
index 289c03416d..56a5bad781 100644
--- a/tests/model_forms/tests.py
+++ b/tests/model_forms/tests.py
@@ -525,11 +525,11 @@ class ModelFormBaseTest(TestCase):
self.assertHTMLEqual(
str(SubclassMeta()),
"""<tr><th><label for="id_name">Name:</label></th>
-<td><input id="id_name" type="text" name="name" maxlength="20" /></td></tr>
+<td><input id="id_name" type="text" name="name" maxlength="20" required /></td></tr>
<tr><th><label for="id_slug">Slug:</label></th>
-<td><input id="id_slug" type="text" name="slug" maxlength="20" /></td></tr>
+<td><input id="id_slug" type="text" name="slug" maxlength="20" required /></td></tr>
<tr><th><label for="id_checkbox">Checkbox:</label></th>
-<td><input type="checkbox" name="checkbox" id="id_checkbox" /></td></tr>"""
+<td><input type="checkbox" name="checkbox" id="id_checkbox" required /></td></tr>"""
)
def test_orderfields_form(self):
@@ -543,9 +543,9 @@ class ModelFormBaseTest(TestCase):
self.assertHTMLEqual(
str(OrderFields()),
"""<tr><th><label for="id_url">The URL:</label></th>
-<td><input id="id_url" type="text" name="url" maxlength="40" /></td></tr>
+<td><input id="id_url" type="text" name="url" maxlength="40" required /></td></tr>
<tr><th><label for="id_name">Name:</label></th>
-<td><input id="id_name" type="text" name="name" maxlength="20" /></td></tr>"""
+<td><input id="id_name" type="text" name="name" maxlength="20" required /></td></tr>"""
)
def test_orderfields2_form(self):
@@ -591,15 +591,15 @@ class TestFieldOverridesByFormMeta(SimpleTestCase):
form = FieldOverridesByFormMetaForm()
self.assertHTMLEqual(
str(form['name']),
- '<textarea id="id_name" rows="10" cols="40" name="name" maxlength="20"></textarea>',
+ '<textarea id="id_name" rows="10" cols="40" name="name" maxlength="20" required></textarea>',
)
self.assertHTMLEqual(
str(form['url']),
- '<input id="id_url" type="text" class="url" name="url" maxlength="40" />',
+ '<input id="id_url" type="text" class="url" name="url" maxlength="40" required />',
)
self.assertHTMLEqual(
str(form['slug']),
- '<input id="id_slug" type="text" name="slug" maxlength="20" />',
+ '<input id="id_slug" type="text" name="slug" maxlength="20" required />',
)
def test_label_overrides(self):
@@ -1041,29 +1041,29 @@ class ModelFormBasicTests(TestCase):
self.assertHTMLEqual(
str(f),
"""<tr><th><label for="id_name">Name:</label></th>
-<td><input id="id_name" type="text" name="name" maxlength="20" /></td></tr>
+<td><input id="id_name" type="text" name="name" maxlength="20" required /></td></tr>
<tr><th><label for="id_slug">Slug:</label></th>
-<td><input id="id_slug" type="text" name="slug" maxlength="20" /></td></tr>
+<td><input id="id_slug" type="text" name="slug" maxlength="20" required /></td></tr>
<tr><th><label for="id_url">The URL:</label></th>
-<td><input id="id_url" type="text" name="url" maxlength="40" /></td></tr>"""
+<td><input id="id_url" type="text" name="url" maxlength="40" required /></td></tr>"""
)
self.assertHTMLEqual(
str(f.as_ul()),
- """<li><label for="id_name">Name:</label> <input id="id_name" type="text" name="name" maxlength="20" /></li>
-<li><label for="id_slug">Slug:</label> <input id="id_slug" type="text" name="slug" maxlength="20" /></li>
-<li><label for="id_url">The URL:</label> <input id="id_url" type="text" name="url" maxlength="40" /></li>"""
+ """<li><label for="id_name">Name:</label> <input id="id_name" type="text" name="name" maxlength="20" required /></li>
+<li><label for="id_slug">Slug:</label> <input id="id_slug" type="text" name="slug" maxlength="20" required /></li>
+<li><label for="id_url">The URL:</label> <input id="id_url" type="text" name="url" maxlength="40" required /></li>"""
)
self.assertHTMLEqual(
str(f["name"]),
- """<input id="id_name" type="text" name="name" maxlength="20" />""")
+ """<input id="id_name" type="text" name="name" maxlength="20" required />""")
def test_auto_id(self):
f = BaseCategoryForm(auto_id=False)
self.assertHTMLEqual(
str(f.as_ul()),
- """<li>Name: <input type="text" name="name" maxlength="20" /></li>
-<li>Slug: <input type="text" name="slug" maxlength="20" /></li>
-<li>The URL: <input type="text" name="url" maxlength="40" /></li>"""
+ """<li>Name: <input type="text" name="name" maxlength="20" required /></li>
+<li>Slug: <input type="text" name="slug" maxlength="20" required /></li>
+<li>The URL: <input type="text" name="url" maxlength="40" required /></li>"""
)
def test_initial_values(self):
@@ -1077,15 +1077,15 @@ class ModelFormBasicTests(TestCase):
})
self.assertHTMLEqual(
f.as_ul(),
- '''<li>Headline: <input type="text" name="headline" value="Your headline here" maxlength="50" /></li>
-<li>Slug: <input type="text" name="slug" maxlength="50" /></li>
-<li>Pub date: <input type="text" name="pub_date" /></li>
-<li>Writer: <select name="writer">
+ '''<li>Headline: <input type="text" name="headline" value="Your headline here" maxlength="50" required /></li>
+<li>Slug: <input type="text" name="slug" maxlength="50" required /></li>
+<li>Pub date: <input type="text" name="pub_date" required /></li>
+<li>Writer: <select name="writer" required>
<option value="" selected="selected">---------</option>
<option value="%s">Bob Woodward</option>
<option value="%s">Mike Royko</option>
</select></li>
-<li>Article: <textarea rows="10" cols="40" name="article"></textarea></li>
+<li>Article: <textarea rows="10" cols="40" name="article" required></textarea></li>
<li>Categories: <select multiple="multiple" name="categories">
<option value="%s" selected="selected">Entertainment</option>
<option value="%s" selected="selected">It&#39;s a test</option>
@@ -1103,7 +1103,7 @@ class ModelFormBasicTests(TestCase):
f = RoykoForm(auto_id=False, instance=self.w_royko)
self.assertHTMLEqual(
six.text_type(f),
- '''<tr><th>Name:</th><td><input type="text" name="name" value="Mike Royko" maxlength="50" /><br />
+ '''<tr><th>Name:</th><td><input type="text" name="name" value="Mike Royko" maxlength="50" required /><br />
<span class="helptext">Use both first and last names.</span></td></tr>'''
)
@@ -1119,15 +1119,15 @@ class ModelFormBasicTests(TestCase):
f = ArticleForm(auto_id=False, instance=art)
self.assertHTMLEqual(
f.as_ul(),
- '''<li>Headline: <input type="text" name="headline" value="Test article" maxlength="50" /></li>
-<li>Slug: <input type="text" name="slug" value="test-article" maxlength="50" /></li>
-<li>Pub date: <input type="text" name="pub_date" value="1988-01-04" /></li>
-<li>Writer: <select name="writer">
+ '''<li>Headline: <input type="text" name="headline" value="Test article" maxlength="50" required /></li>
+<li>Slug: <input type="text" name="slug" value="test-article" maxlength="50" required /></li>
+<li>Pub date: <input type="text" name="pub_date" value="1988-01-04" required /></li>
+<li>Writer: <select name="writer" required>
<option value="">---------</option>
<option value="%s">Bob Woodward</option>
<option value="%s" selected="selected">Mike Royko</option>
</select></li>
-<li>Article: <textarea rows="10" cols="40" name="article">Hello.</textarea></li>
+<li>Article: <textarea rows="10" cols="40" name="article" required>Hello.</textarea></li>
<li>Categories: <select multiple="multiple" name="categories">
<option value="%s">Entertainment</option>
<option value="%s">It&#39;s a test</option>
@@ -1174,7 +1174,7 @@ class ModelFormBasicTests(TestCase):
self.assertHTMLEqual(
form.as_ul(),
"""<li><label for="id_headline">Headline:</label>
-<input id="id_headline" type="text" name="headline" maxlength="50" /></li>
+<input id="id_headline" type="text" name="headline" maxlength="50" required /></li>
<li><label for="id_categories">Categories:</label>
<select multiple="multiple" name="categories" id="id_categories">
<option value="%d" selected="selected">Entertainment</option>
@@ -1235,15 +1235,15 @@ class ModelFormBasicTests(TestCase):
f = ArticleForm(auto_id=False)
self.assertHTMLEqual(
six.text_type(f),
- '''<tr><th>Headline:</th><td><input type="text" name="headline" maxlength="50" /></td></tr>
-<tr><th>Slug:</th><td><input type="text" name="slug" maxlength="50" /></td></tr>
-<tr><th>Pub date:</th><td><input type="text" name="pub_date" /></td></tr>
-<tr><th>Writer:</th><td><select name="writer">
+ '''<tr><th>Headline:</th><td><input type="text" name="headline" maxlength="50" required /></td></tr>
+<tr><th>Slug:</th><td><input type="text" name="slug" maxlength="50" required /></td></tr>
+<tr><th>Pub date:</th><td><input type="text" name="pub_date" required /></td></tr>
+<tr><th>Writer:</th><td><select name="writer" required>
<option value="" selected="selected">---------</option>
<option value="%s">Bob Woodward</option>
<option value="%s">Mike Royko</option>
</select></td></tr>
-<tr><th>Article:</th><td><textarea rows="10" cols="40" name="article"></textarea></td></tr>
+<tr><th>Article:</th><td><textarea rows="10" cols="40" name="article" required></textarea></td></tr>
<tr><th>Categories:</th><td><select multiple="multiple" name="categories">
<option value="%s">Entertainment</option>
<option value="%s">It&#39;s a test</option>
@@ -1265,15 +1265,15 @@ class ModelFormBasicTests(TestCase):
f = ArticleForm(auto_id=False, instance=new_art)
self.assertHTMLEqual(
f.as_ul(),
- '''<li>Headline: <input type="text" name="headline" value="New headline" maxlength="50" /></li>
-<li>Slug: <input type="text" name="slug" value="new-headline" maxlength="50" /></li>
-<li>Pub date: <input type="text" name="pub_date" value="1988-01-04" /></li>
-<li>Writer: <select name="writer">
+ '''<li>Headline: <input type="text" name="headline" value="New headline" maxlength="50" required /></li>
+<li>Slug: <input type="text" name="slug" value="new-headline" maxlength="50" required /></li>
+<li>Pub date: <input type="text" name="pub_date" value="1988-01-04" required /></li>
+<li>Writer: <select name="writer" required>
<option value="">---------</option>
<option value="%s">Bob Woodward</option>
<option value="%s" selected="selected">Mike Royko</option>
</select></li>
-<li>Article: <textarea rows="10" cols="40" name="article">Hello.</textarea></li>
+<li>Article: <textarea rows="10" cols="40" name="article" required>Hello.</textarea></li>
<li>Categories: <select multiple="multiple" name="categories">
<option value="%s" selected="selected">Entertainment</option>
<option value="%s">It&#39;s a test</option>
@@ -1301,8 +1301,8 @@ class ModelFormBasicTests(TestCase):
f = PartialArticleForm(auto_id=False)
self.assertHTMLEqual(
six.text_type(f),
- '''<tr><th>Headline:</th><td><input type="text" name="headline" maxlength="50" /></td></tr>
-<tr><th>Pub date:</th><td><input type="text" name="pub_date" /></td></tr>''')
+ '''<tr><th>Headline:</th><td><input type="text" name="headline" maxlength="50" required /></td></tr>
+<tr><th>Pub date:</th><td><input type="text" name="pub_date" required /></td></tr>''')
# You can create a form over a subset of the available fields
# by specifying a 'fields' argument to form_for_instance.
@@ -1322,9 +1322,9 @@ class ModelFormBasicTests(TestCase):
}, auto_id=False, instance=art)
self.assertHTMLEqual(
f.as_ul(),
- '''<li>Headline: <input type="text" name="headline" value="New headline" maxlength="50" /></li>
-<li>Slug: <input type="text" name="slug" value="new-headline" maxlength="50" /></li>
-<li>Pub date: <input type="text" name="pub_date" value="1988-01-04" /></li>'''
+ '''<li>Headline: <input type="text" name="headline" value="New headline" maxlength="50" required /></li>
+<li>Slug: <input type="text" name="slug" value="new-headline" maxlength="50" required /></li>
+<li>Pub date: <input type="text" name="pub_date" value="1988-01-04" required /></li>'''
)
self.assertTrue(f.is_valid())
new_art = f.save()
@@ -1411,15 +1411,15 @@ class ModelFormBasicTests(TestCase):
f = ArticleForm(auto_id=False)
self.assertHTMLEqual(
f.as_ul(),
- '''<li>Headline: <input type="text" name="headline" maxlength="50" /></li>
-<li>Slug: <input type="text" name="slug" maxlength="50" /></li>
-<li>Pub date: <input type="text" name="pub_date" /></li>
-<li>Writer: <select name="writer">
+ '''<li>Headline: <input type="text" name="headline" maxlength="50" required /></li>
+<li>Slug: <input type="text" name="slug" maxlength="50" required /></li>
+<li>Pub date: <input type="text" name="pub_date" required /></li>
+<li>Writer: <select name="writer" required>
<option value="" selected="selected">---------</option>
<option value="%s">Bob Woodward</option>
<option value="%s">Mike Royko</option>
</select></li>
-<li>Article: <textarea rows="10" cols="40" name="article"></textarea></li>
+<li>Article: <textarea rows="10" cols="40" name="article" required></textarea></li>
<li>Categories: <select multiple="multiple" name="categories">
<option value="%s">Entertainment</option>
<option value="%s">It&#39;s a test</option>
@@ -1436,16 +1436,16 @@ class ModelFormBasicTests(TestCase):
w_bernstein = Writer.objects.create(name='Carl Bernstein')
self.assertHTMLEqual(
f.as_ul(),
- '''<li>Headline: <input type="text" name="headline" maxlength="50" /></li>
-<li>Slug: <input type="text" name="slug" maxlength="50" /></li>
-<li>Pub date: <input type="text" name="pub_date" /></li>
-<li>Writer: <select name="writer">
+ '''<li>Headline: <input type="text" name="headline" maxlength="50" required /></li>
+<li>Slug: <input type="text" name="slug" maxlength="50" required /></li>
+<li>Pub date: <input type="text" name="pub_date" required /></li>
+<li>Writer: <select name="writer" required>
<option value="" selected="selected">---------</option>
<option value="%s">Bob Woodward</option>
<option value="%s">Carl Bernstein</option>
<option value="%s">Mike Royko</option>
</select></li>
-<li>Article: <textarea rows="10" cols="40" name="article"></textarea></li>
+<li>Article: <textarea rows="10" cols="40" name="article" required></textarea></li>
<li>Categories: <select multiple="multiple" name="categories">
<option value="%s">Entertainment</option>
<option value="%s">It&#39;s a test</option>
@@ -1798,12 +1798,12 @@ class ModelOneToOneFieldTests(TestCase):
form = WriterProfileForm()
self.assertHTMLEqual(
form.as_p(),
- '''<p><label for="id_writer">Writer:</label> <select name="writer" id="id_writer">
+ '''<p><label for="id_writer">Writer:</label> <select name="writer" id="id_writer" required>
<option value="" selected="selected">---------</option>
<option value="%s">Bob Woodward</option>
<option value="%s">Mike Royko</option>
</select></p>
-<p><label for="id_age">Age:</label> <input type="number" name="age" id="id_age" min="0" /></p>''' % (
+<p><label for="id_age">Age:</label> <input type="number" name="age" id="id_age" min="0" required /></p>''' % (
self.w_woodward.pk, self.w_royko.pk,
)
)
@@ -1819,12 +1819,13 @@ class ModelOneToOneFieldTests(TestCase):
form = WriterProfileForm(instance=instance)
self.assertHTMLEqual(
form.as_p(),
- '''<p><label for="id_writer">Writer:</label> <select name="writer" id="id_writer">
+ '''<p><label for="id_writer">Writer:</label> <select name="writer" id="id_writer" required>
<option value="">---------</option>
<option value="%s" selected="selected">Bob Woodward</option>
<option value="%s">Mike Royko</option>
</select></p>
-<p><label for="id_age">Age:</label> <input type="number" name="age" value="65" id="id_age" min="0" /></p>''' % (
+<p><label for="id_age">Age:</label>
+<input type="number" name="age" value="65" id="id_age" min="0" required /></p>''' % (
self.w_woodward.pk, self.w_royko.pk,
)
)
@@ -2403,9 +2404,9 @@ class OtherModelFormTests(TestCase):
self.assertHTMLEqual(
six.text_type(CategoryForm()),
'''<tr><th><label for="id_description">Description:</label></th>
-<td><input type="text" name="description" id="id_description" /></td></tr>
+<td><input type="text" name="description" id="id_description" required /></td></tr>
<tr><th><label for="id_url">The URL:</label></th>
-<td><input id="id_url" type="text" name="url" maxlength="40" /></td></tr>'''
+<td><input id="id_url" type="text" name="url" maxlength="40" required /></td></tr>'''
)
# to_field_name should also work on ModelMultipleChoiceField ##################
@@ -2424,7 +2425,7 @@ class OtherModelFormTests(TestCase):
self.assertHTMLEqual(
six.text_type(CustomFieldForExclusionForm()),
'''<tr><th><label for="id_name">Name:</label></th>
-<td><input id="id_name" type="text" name="name" maxlength="10" /></td></tr>'''
+<td><input id="id_name" type="text" name="name" maxlength="10" required /></td></tr>'''
)
def test_iterable_model_m2m(self):
@@ -2438,8 +2439,9 @@ class OtherModelFormTests(TestCase):
self.maxDiff = 1024
self.assertHTMLEqual(
form.as_p(),
- """<p><label for="id_name">Name:</label> <input id="id_name" type="text" name="name" maxlength="50" /></p>
- <p><label for="id_colours">Colours:</label> <select multiple="multiple" name="colours" id="id_colours">
+ """<p><label for="id_name">Name:</label> <input id="id_name" type="text" name="name" maxlength="50" required /></p>
+ <p><label for="id_colours">Colours:</label>
+ <select multiple="multiple" name="colours" id="id_colours" required>
<option value="%(blue_pk)s">Blue</option>
</select></p>"""
% {'blue_pk': colour.pk})
@@ -2456,15 +2458,16 @@ class OtherModelFormTests(TestCase):
self.assertHTMLEqual(
form.as_p(),
"""
- <p><label for="id_title">Title:</label> <input id="id_title" maxlength="30" name="title" type="text" /></p>
+ <p><label for="id_title">Title:</label>
+ <input id="id_title" maxlength="30" name="title" type="text" required /></p>
<p><label for="id_date_published">Date published:</label>
- <input id="id_date_published" name="date_published" type="text" value="{0}" />
+ <input id="id_date_published" name="date_published" type="text" value="{0}" required />
<input id="initial-id_date_published" name="initial-date_published" type="hidden" value="{0}" /></p>
- <p><label for="id_mode">Mode:</label> <select id="id_mode" name="mode">
+ <p><label for="id_mode">Mode:</label> <select id="id_mode" name="mode" required>
<option value="di" selected="selected">direct</option>
<option value="de">delayed</option></select>
<input id="initial-id_mode" name="initial-mode" type="hidden" value="di" /></p>
- <p><label for="id_category">Category:</label> <select id="id_category" name="category">
+ <p><label for="id_category">Category:</label> <select id="id_category" name="category" required>
<option value="1">Games</option>
<option value="2">Comics</option>
<option value="3" selected="selected">Novel</option></select>
diff --git a/tests/model_formsets/tests.py b/tests/model_formsets/tests.py
index 4e909e5f5b..0739a6b1e0 100644
--- a/tests/model_formsets/tests.py
+++ b/tests/model_formsets/tests.py
@@ -1641,7 +1641,7 @@ class TestModelFormsetOverridesTroughFormMeta(TestCase):
form = PoetFormSet.form()
self.assertHTMLEqual(
"%s" % form['name'],
- '<input id="id_name" maxlength="100" type="text" class="poet" name="name" />'
+ '<input id="id_name" maxlength="100" type="text" class="poet" name="name" required />'
)
def test_inlineformset_factory_widgets(self):
@@ -1652,7 +1652,7 @@ class TestModelFormsetOverridesTroughFormMeta(TestCase):
form = BookFormSet.form()
self.assertHTMLEqual(
"%s" % form['title'],
- '<input class="book" id="id_title" maxlength="100" name="title" type="text" />'
+ '<input class="book" id="id_title" maxlength="100" name="title" type="text" required />'
)
def test_modelformset_factory_labels_overrides(self):
diff --git a/tests/modeladmin/tests.py b/tests/modeladmin/tests.py
index 0de3fb5925..990ed9ab32 100644
--- a/tests/modeladmin/tests.py
+++ b/tests/modeladmin/tests.py
@@ -359,7 +359,7 @@ class ModelAdminTests(TestCase):
self.assertHTMLEqual(
str(form["main_band"]),
'<div class="related-widget-wrapper">'
- '<select name="main_band" id="id_main_band">'
+ '<select name="main_band" id="id_main_band" required>'
'<option value="" selected="selected">---------</option>'
'<option value="%d">The Beatles</option>'
'<option value="%d">The Doors</option>'
@@ -380,7 +380,7 @@ class ModelAdminTests(TestCase):
self.assertHTMLEqual(
str(form["main_band"]),
'<div class="related-widget-wrapper">'
- '<select name="main_band" id="id_main_band">'
+ '<select name="main_band" id="id_main_band" required>'
'<option value="" selected="selected">---------</option>'
'<option value="%d">The Doors</option>'
'</select></div>' % self.band.id
diff --git a/tests/postgres_tests/test_array.py b/tests/postgres_tests/test_array.py
index 670c98e7a7..edbc1d9241 100644
--- a/tests/postgres_tests/test_array.py
+++ b/tests/postgres_tests/test_array.py
@@ -699,9 +699,9 @@ class TestSplitFormField(PostgreSQLTestCase):
<tr>
<th><label for="id_array_0">Array:</label></th>
<td>
- <input id="id_array_0" name="array_0" type="text" />
- <input id="id_array_1" name="array_1" type="text" />
- <input id="id_array_2" name="array_2" type="text" />
+ <input id="id_array_0" name="array_0" type="text" required />
+ <input id="id_array_1" name="array_1" type="text" required />
+ <input id="id_array_2" name="array_2" type="text" required />
</td>
</tr>
''')