|
@@ -161,6 +161,15 @@ class FormsTestCase(SimpleTestCase):
|
|
|
required></td></tr>
|
|
|
""",
|
|
|
)
|
|
|
+ self.assertHTMLEqual(
|
|
|
+ p.as_div(),
|
|
|
+ '<div><label for="id_first_name">First name:</label><input type="text" '
|
|
|
+ 'name="first_name" value="John" required id="id_first_name"></div><div>'
|
|
|
+ '<label for="id_last_name">Last name:</label><input type="text" '
|
|
|
+ 'name="last_name" value="Lennon" required id="id_last_name"></div><div>'
|
|
|
+ '<label for="id_birthday">Birthday:</label><input type="text" '
|
|
|
+ 'name="birthday" value="1940-10-9" required id="id_birthday"></div>',
|
|
|
+ )
|
|
|
|
|
|
def test_empty_dict(self):
|
|
|
# Empty dictionaries are valid, too.
|
|
@@ -219,6 +228,18 @@ class FormsTestCase(SimpleTestCase):
|
|
|
<p><label for="id_birthday">Birthday:</label>
|
|
|
<input type="text" name="birthday" id="id_birthday" required></p>""",
|
|
|
)
|
|
|
+ self.assertHTMLEqual(
|
|
|
+ p.as_div(),
|
|
|
+ '<div><label for="id_first_name">First name:</label>'
|
|
|
+ '<ul class="errorlist"><li>This field is required.</li></ul>'
|
|
|
+ '<input type="text" name="first_name" required id="id_first_name"></div>'
|
|
|
+ '<div><label for="id_last_name">Last name:</label>'
|
|
|
+ '<ul class="errorlist"><li>This field is required.</li></ul>'
|
|
|
+ '<input type="text" name="last_name" required id="id_last_name"></div><div>'
|
|
|
+ '<label for="id_birthday">Birthday:</label>'
|
|
|
+ '<ul class="errorlist"><li>This field is required.</li></ul>'
|
|
|
+ '<input type="text" name="birthday" required id="id_birthday"></div>',
|
|
|
+ )
|
|
|
|
|
|
def test_empty_querydict_args(self):
|
|
|
data = QueryDict()
|
|
@@ -274,6 +295,15 @@ class FormsTestCase(SimpleTestCase):
|
|
|
<p><label for="id_birthday">Birthday:</label>
|
|
|
<input type="text" name="birthday" id="id_birthday" required></p>""",
|
|
|
)
|
|
|
+ self.assertHTMLEqual(
|
|
|
+ p.as_div(),
|
|
|
+ '<div><label for="id_first_name">First name:</label><input type="text" '
|
|
|
+ 'name="first_name" id="id_first_name" required></div><div><label '
|
|
|
+ 'for="id_last_name">Last name:</label><input type="text" name="last_name" '
|
|
|
+ 'id="id_last_name" required></div><div><label for="id_birthday">'
|
|
|
+ 'Birthday:</label><input type="text" name="birthday" id="id_birthday" '
|
|
|
+ "required></div>",
|
|
|
+ )
|
|
|
|
|
|
def test_unicode_values(self):
|
|
|
# Unicode values are handled properly.
|
|
@@ -323,6 +353,17 @@ class FormsTestCase(SimpleTestCase):
|
|
|
'<input type="text" name="birthday" value="1940-10-9" id="id_birthday" '
|
|
|
"required></p>",
|
|
|
)
|
|
|
+ self.assertHTMLEqual(
|
|
|
+ p.as_div(),
|
|
|
+ '<div><label for="id_first_name">First name:</label>'
|
|
|
+ '<input type="text" name="first_name" value="John" id="id_first_name" '
|
|
|
+ 'required></div><div><label for="id_last_name">Last name:</label>'
|
|
|
+ '<input type="text" name="last_name"'
|
|
|
+ 'value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" '
|
|
|
+ 'id="id_last_name" required></div><div><label for="id_birthday">'
|
|
|
+ 'Birthday:</label><input type="text" name="birthday" value="1940-10-9" '
|
|
|
+ 'id="id_birthday" required></div>',
|
|
|
+ )
|
|
|
|
|
|
p = Person({"last_name": "Lennon"})
|
|
|
self.assertEqual(p.errors["first_name"], ["This field is required."])
|
|
@@ -439,6 +480,15 @@ class FormsTestCase(SimpleTestCase):
|
|
|
<p><label for="birthday_id">Birthday:</label>
|
|
|
<input type="text" name="birthday" id="birthday_id" required></p>""",
|
|
|
)
|
|
|
+ self.assertHTMLEqual(
|
|
|
+ p.as_div(),
|
|
|
+ '<div><label for="first_name_id">First name:</label><input type="text" '
|
|
|
+ 'name="first_name" id="first_name_id" required></div><div><label '
|
|
|
+ 'for="last_name_id">Last name:</label><input type="text" '
|
|
|
+ 'name="last_name" id="last_name_id" required></div><div><label '
|
|
|
+ 'for="birthday_id">Birthday:</label><input type="text" name="birthday" '
|
|
|
+ 'id="birthday_id" required></div>',
|
|
|
+ )
|
|
|
|
|
|
def test_auto_id_true(self):
|
|
|
# If auto_id is any True value whose str() does not contain '%s', the "id"
|
|
@@ -746,6 +796,15 @@ class FormsTestCase(SimpleTestCase):
|
|
|
<div><label><input type="radio" name="language" value="J" required> Java</label></div>
|
|
|
</div></li>""",
|
|
|
)
|
|
|
+ # Need an auto_id to generate legend.
|
|
|
+ self.assertHTMLEqual(
|
|
|
+ f.render(f.template_name_div),
|
|
|
+ '<div> Name: <input type="text" name="name" required></div><div><fieldset>'
|
|
|
+ 'Language:<div><div><label><input type="radio" name="language" value="P" '
|
|
|
+ 'required> Python</label></div><div><label><input type="radio" '
|
|
|
+ 'name="language" value="J" required> Java</label></div></div></fieldset>'
|
|
|
+ "</div>",
|
|
|
+ )
|
|
|
|
|
|
# Regarding auto_id and <label>, RadioSelect is a special case. Each
|
|
|
# radio button gets a distinct ID, formed by appending an underscore
|
|
@@ -812,6 +871,16 @@ class FormsTestCase(SimpleTestCase):
|
|
|
</div></p>
|
|
|
""",
|
|
|
)
|
|
|
+ self.assertHTMLEqual(
|
|
|
+ f.render(f.template_name_div),
|
|
|
+ '<div><label for="id_name">Name:</label><input type="text" name="name" '
|
|
|
+ 'required id="id_name"></div><div><fieldset><legend>Language:</legend>'
|
|
|
+ '<div id="id_language"><div><label for="id_language_0"><input '
|
|
|
+ 'type="radio" name="language" value="P" required id="id_language_0">'
|
|
|
+ 'Python</label></div><div><label for="id_language_1"><input type="radio" '
|
|
|
+ 'name="language" value="J" required id="id_language_1">Java</label></div>'
|
|
|
+ "</div></fieldset></div>",
|
|
|
+ )
|
|
|
|
|
|
def test_form_with_iterable_boundfield(self):
|
|
|
class BeatleForm(Form):
|
|
@@ -1022,6 +1091,14 @@ class FormsTestCase(SimpleTestCase):
|
|
|
'<option value="P">Paul McCartney</option>'
|
|
|
"</select></p>",
|
|
|
)
|
|
|
+ self.assertHTMLEqual(
|
|
|
+ f.render(f.template_name_div),
|
|
|
+ '<div><label for="id_name">Name:</label><input type="text" name="name" '
|
|
|
+ 'required id="id_name"></div><div><label for="id_composers">Composers:'
|
|
|
+ '</label><select name="composers" required id="id_composers" multiple>'
|
|
|
+ '<option value="J">John Lennon</option><option value="P">Paul McCartney'
|
|
|
+ "</option></select></div>",
|
|
|
+ )
|
|
|
|
|
|
def test_multiple_checkbox_render(self):
|
|
|
f = SongForm()
|
|
@@ -1064,6 +1141,16 @@ class FormsTestCase(SimpleTestCase):
|
|
|
'id="id_composers_1">Paul McCartney</label></div>'
|
|
|
"</div></p>",
|
|
|
)
|
|
|
+ self.assertHTMLEqual(
|
|
|
+ f.render(f.template_name_div),
|
|
|
+ '<div><label for="id_name">Name:</label><input type="text" name="name" '
|
|
|
+ 'required id="id_name"></div><div><fieldset><legend>Composers:</legend>'
|
|
|
+ '<div id="id_composers"><div><label for="id_composers_0"><input '
|
|
|
+ 'type="checkbox" name="composers" value="J" id="id_composers_0">'
|
|
|
+ 'John Lennon</label></div><div><label for="id_composers_1"><input '
|
|
|
+ 'type="checkbox" name="composers" value="P" id="id_composers_1">'
|
|
|
+ "Paul McCartney</label></div></div></fieldset></div>",
|
|
|
+ )
|
|
|
|
|
|
def test_form_with_disabled_fields(self):
|
|
|
class PersonForm(Form):
|
|
@@ -1492,6 +1579,14 @@ class FormsTestCase(SimpleTestCase):
|
|
|
<li>Password2: <input type="password" name="password2" required></li>
|
|
|
""",
|
|
|
)
|
|
|
+ self.assertHTMLEqual(
|
|
|
+ f.render(f.template_name_div),
|
|
|
+ '<ul class="errorlist nonfield"><li>Please make sure your passwords match.'
|
|
|
+ '</li></ul><div>Username: <input type="text" name="username" '
|
|
|
+ 'value="adrian" maxlength="10" required></div><div>Password1: <input '
|
|
|
+ 'type="password" name="password1" required></div><div>Password2: <input '
|
|
|
+ 'type="password" name="password2" required></div>',
|
|
|
+ )
|
|
|
|
|
|
f = UserRegistration(
|
|
|
{"username": "adrian", "password1": "foo", "password2": "foo"},
|
|
@@ -1649,6 +1744,12 @@ class FormsTestCase(SimpleTestCase):
|
|
|
"<li>(Hidden field hidden_input) This field is required.</li></ul>"
|
|
|
'<p><input type="hidden" name="hidden_input" id="id_hidden_input"></p>',
|
|
|
)
|
|
|
+ self.assertHTMLEqual(
|
|
|
+ f.render(f.template_name_div),
|
|
|
+ '<ul class="errorlist nonfield"><li>Form error</li>'
|
|
|
+ "<li>(Hidden field hidden_input) This field is required.</li></ul>"
|
|
|
+ '<div><input type="hidden" name="hidden_input" id="id_hidden_input"></div>',
|
|
|
+ )
|
|
|
|
|
|
def test_dynamic_construction(self):
|
|
|
# It's possible to construct a Form dynamically by adding to the self.fields
|
|
@@ -1893,6 +1994,13 @@ class FormsTestCase(SimpleTestCase):
|
|
|
<input type="hidden" name="hidden_text"></p>
|
|
|
""",
|
|
|
)
|
|
|
+ self.assertHTMLEqual(
|
|
|
+ p.as_div(),
|
|
|
+ '<div>First name: <input type="text" name="first_name" required></div>'
|
|
|
+ '<div>Last name: <input type="text" name="last_name" required></div><div>'
|
|
|
+ 'Birthday: <input type="text" name="birthday" required><input '
|
|
|
+ 'type="hidden" name="hidden_text"></div>',
|
|
|
+ )
|
|
|
|
|
|
# With auto_id set, a HiddenInput still gets an ID, but it doesn't get a label.
|
|
|
p = Person(auto_id="id_%s")
|
|
@@ -1926,6 +2034,15 @@ class FormsTestCase(SimpleTestCase):
|
|
|
<input type="text" name="birthday" id="id_birthday" required>
|
|
|
<input type="hidden" name="hidden_text" id="id_hidden_text"></p>""",
|
|
|
)
|
|
|
+ self.assertHTMLEqual(
|
|
|
+ p.as_div(),
|
|
|
+ '<div><label for="id_first_name">First name:</label><input type="text" '
|
|
|
+ 'name="first_name" id="id_first_name" required></div><div><label '
|
|
|
+ 'for="id_last_name">Last name:</label><input type="text" name="last_name" '
|
|
|
+ 'id="id_last_name" required></div><div><label for="id_birthday">Birthday:'
|
|
|
+ '</label><input type="text" name="birthday" id="id_birthday" required>'
|
|
|
+ '<input type="hidden" name="hidden_text" id="id_hidden_text"></div>',
|
|
|
+ )
|
|
|
|
|
|
# If a field with a HiddenInput has errors, the as_table() and as_ul() output
|
|
|
# will include the error message(s) with the text "(Hidden field [fieldname]) "
|
|
@@ -1976,6 +2093,15 @@ class FormsTestCase(SimpleTestCase):
|
|
|
<input type="hidden" name="hidden_text"></p>
|
|
|
""",
|
|
|
)
|
|
|
+ self.assertHTMLEqual(
|
|
|
+ p.as_div(),
|
|
|
+ '<ul class="errorlist nonfield"><li>(Hidden field hidden_text) This field '
|
|
|
+ 'is required.</li></ul><div>First name: <input type="text" '
|
|
|
+ 'name="first_name" value="John" required></div><div>Last name: <input '
|
|
|
+ 'type="text" name="last_name" value="Lennon" required></div><div>'
|
|
|
+ 'Birthday: <input type="text" name="birthday" value="1940-10-9" required>'
|
|
|
+ '<input type="hidden" name="hidden_text"></div>',
|
|
|
+ )
|
|
|
|
|
|
# A corner case: It's possible for a form to have only HiddenInputs.
|
|
|
class TestForm(Form):
|
|
@@ -2811,6 +2937,13 @@ Options: <select multiple name="options" required>
|
|
|
<br>
|
|
|
<span class="helptext">Wählen Sie mit Bedacht.</span></td></tr>""",
|
|
|
)
|
|
|
+ self.assertHTMLEqual(
|
|
|
+ p.as_div(),
|
|
|
+ '<div>Username: <div class="helptext">e.g., user@example.com</div>'
|
|
|
+ '<input type="text" name="username" maxlength="10" required></div>'
|
|
|
+ '<div>Password: <div class="helptext">Wählen Sie mit Bedacht.</div>'
|
|
|
+ '<input type="password" name="password" required></div>',
|
|
|
+ )
|
|
|
|
|
|
# The help text is displayed whether or not data is provided for the form.
|
|
|
p = UserRegistration({"username": "foo"}, auto_id=False)
|
|
@@ -3431,6 +3564,21 @@ Password: <input type="password" name="password" required>
|
|
|
<td><ul class="errorlist"><li>This field is required.</li></ul>
|
|
|
<input type="number" name="age" id="id_age" required></td></tr>""",
|
|
|
)
|
|
|
+ self.assertHTMLEqual(
|
|
|
+ p.as_div(),
|
|
|
+ '<div class="required error"><label for="id_name" class="required">Name:'
|
|
|
+ '</label><ul class="errorlist"><li>This field is required.</li></ul>'
|
|
|
+ '<input type="text" name="name" required id="id_name" /></div>'
|
|
|
+ '<div class="required"><label for="id_is_cool" class="required">Is cool:'
|
|
|
+ '</label><select name="is_cool" id="id_is_cool">'
|
|
|
+ '<option value="unknown" selected>Unknown</option>'
|
|
|
+ '<option value="true">Yes</option><option value="false">No</option>'
|
|
|
+ '</select></div><div><label for="id_email">Email:</label>'
|
|
|
+ '<input type="email" name="email" id="id_email" /></div>'
|
|
|
+ '<div class="required error"><label for="id_age" class="required">Age:'
|
|
|
+ '</label><ul class="errorlist"><li>This field is required.</li></ul>'
|
|
|
+ '<input type="number" name="age" required id="id_age" /></div>',
|
|
|
+ )
|
|
|
|
|
|
def test_label_has_required_css_class(self):
|
|
|
"""
|
|
@@ -4027,6 +4175,13 @@ Password: <input type="password" name="password" required>
|
|
|
<input id="id_first_name" name="first_name" type="text" value="John" required>
|
|
|
<input id="id_last_name" name="last_name" type="hidden"></td></tr>""",
|
|
|
)
|
|
|
+ self.assertHTMLEqual(
|
|
|
+ p.as_div(),
|
|
|
+ '<ul class="errorlist nonfield"><li>(Hidden field last_name) This field '
|
|
|
+ 'is required.</li></ul><div><label for="id_first_name">First name:</label>'
|
|
|
+ '<input id="id_first_name" name="first_name" type="text" value="John" '
|
|
|
+ 'required><input id="id_last_name" name="last_name" type="hidden"></div>',
|
|
|
+ )
|
|
|
|
|
|
def test_error_list_with_non_field_errors_has_correct_class(self):
|
|
|
class Person(Form):
|
|
@@ -4076,6 +4231,15 @@ Password: <input type="password" name="password" required>
|
|
|
</td></tr>
|
|
|
""",
|
|
|
)
|
|
|
+ self.assertHTMLEqual(
|
|
|
+ p.as_div(),
|
|
|
+ '<ul class="errorlist nonfield"><li>Generic validation error</li></ul>'
|
|
|
+ '<div><label for="id_first_name">First name:</label><input '
|
|
|
+ 'id="id_first_name" name="first_name" type="text" value="John" required>'
|
|
|
+ '</div><div><label for="id_last_name">Last name:</label><input '
|
|
|
+ 'id="id_last_name" name="last_name" type="text" value="Lennon" required>'
|
|
|
+ "</div>",
|
|
|
+ )
|
|
|
|
|
|
def test_error_escaping(self):
|
|
|
class TestForm(Form):
|
|
@@ -4271,6 +4435,16 @@ Password: <input type="password" name="password" required>
|
|
|
'<option value="J">Java</option>'
|
|
|
"</select></td></tr>",
|
|
|
)
|
|
|
+ self.assertHTMLEqual(
|
|
|
+ form.render(form.template_name_div),
|
|
|
+ '<div><label for="id_f1">F1:</label><input id="id_f1" maxlength="30" '
|
|
|
+ 'name="f1" type="text" required></div><div><label for="id_f2">F2:</label>'
|
|
|
+ '<input id="id_f2" maxlength="30" name="f2" type="text"></div><div><label '
|
|
|
+ 'for="id_f3">F3:</label><textarea cols="40" id="id_f3" name="f3" '
|
|
|
+ 'rows="10" required></textarea></div><div><label for="id_f4">F4:</label>'
|
|
|
+ '<select id="id_f4" name="f4"><option value="P">Python</option>'
|
|
|
+ '<option value="J">Java</option></select></div>',
|
|
|
+ )
|
|
|
|
|
|
def test_use_required_attribute_false(self):
|
|
|
class MyForm(Form):
|
|
@@ -4322,6 +4496,16 @@ Password: <input type="password" name="password" required>
|
|
|
'<option value="J">Java</option>'
|
|
|
"</select></td></tr>",
|
|
|
)
|
|
|
+ self.assertHTMLEqual(
|
|
|
+ form.render(form.template_name_div),
|
|
|
+ '<div><label for="id_f1">F1:</label> <input id="id_f1" maxlength="30" '
|
|
|
+ 'name="f1" type="text"></div><div><label for="id_f2">F2:</label>'
|
|
|
+ '<input id="id_f2" maxlength="30" name="f2" type="text"></div><div>'
|
|
|
+ '<label for="id_f3">F3:</label> <textarea cols="40" id="id_f3" name="f3" '
|
|
|
+ 'rows="10"></textarea></div><div><label for="id_f4">F4:</label>'
|
|
|
+ '<select id="id_f4" name="f4"><option value="P">Python</option>'
|
|
|
+ '<option value="J">Java</option></select></div>',
|
|
|
+ )
|
|
|
|
|
|
def test_only_hidden_fields(self):
|
|
|
# A form with *only* hidden fields that has errors is going to be very unusual.
|