Fixed #22383 -- Added support for HTML5 required attribute on required form fields.
This commit is contained in:
parent
4d1c229ee5
commit
ec6121693f
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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::
|
||||
|
||||
|
|
|
@ -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``
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 />')
|
||||
|
|
|
@ -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>'
|
||||
)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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'))
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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>
|
||||
""",
|
||||
)
|
||||
|
||||
|
|
|
@ -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'))
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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>'
|
||||
)
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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'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'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'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'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'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'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>
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
''')
|
||||
|
|
Loading…
Reference in New Issue