|
@@ -256,6 +256,27 @@ class FormsFormsetTestCase(TestCase):
|
|
|
self.assertTrue(formset.is_valid())
|
|
|
self.assertEqual([form.cleaned_data for form in formset.forms], [{'votes': 100, 'choice': 'Calexico'}, {}, {}])
|
|
|
|
|
|
+ def test_formset_validate_max_flag(self):
|
|
|
+ # If validate_max is set and max_num is less than TOTAL_FORMS in the
|
|
|
+ # data, then throw an exception. MAX_NUM_FORMS in the data is
|
|
|
+ # irrelevant here (it's output as a hint for the client but its
|
|
|
+ # value in the returned data is not checked)
|
|
|
+
|
|
|
+ data = {
|
|
|
+ 'choices-TOTAL_FORMS': '2', # the number of forms rendered
|
|
|
+ 'choices-INITIAL_FORMS': '0', # the number of forms with initial data
|
|
|
+ 'choices-MAX_NUM_FORMS': '2', # max number of forms - should be ignored
|
|
|
+ 'choices-0-choice': 'Zero',
|
|
|
+ 'choices-0-votes': '0',
|
|
|
+ 'choices-1-choice': 'One',
|
|
|
+ 'choices-1-votes': '1',
|
|
|
+ }
|
|
|
+
|
|
|
+ ChoiceFormSet = formset_factory(Choice, extra=1, max_num=1, validate_max=True)
|
|
|
+ formset = ChoiceFormSet(data, auto_id=False, prefix='choices')
|
|
|
+ self.assertFalse(formset.is_valid())
|
|
|
+ self.assertEqual(formset.non_form_errors(), ['Please submit 1 or fewer forms.'])
|
|
|
+
|
|
|
def test_second_form_partially_filled_2(self):
|
|
|
# And once again, if we try to partially complete a form, validation will fail.
|
|
|
|
|
@@ -720,8 +741,20 @@ class FormsFormsetTestCase(TestCase):
|
|
|
<tr><th><label for="id_form-1-name">Name:</label></th><td><input type="text" name="form-1-name" id="id_form-1-name" /></td></tr>""")
|
|
|
|
|
|
def test_max_num_zero(self):
|
|
|
- # If max_num is 0 then no form is rendered at all, even if extra and initial
|
|
|
- # are specified.
|
|
|
+ # If max_num is 0 then no form is rendered at all, regardless of extra,
|
|
|
+ # unless initial data is present. (This changed in the patch for bug
|
|
|
+ # 20084 -- previously max_num=0 trumped initial data)
|
|
|
+
|
|
|
+ LimitedFavoriteDrinkFormSet = formset_factory(FavoriteDrinkForm, extra=1, max_num=0)
|
|
|
+ formset = LimitedFavoriteDrinkFormSet()
|
|
|
+ form_output = []
|
|
|
+
|
|
|
+ for form in formset.forms:
|
|
|
+ form_output.append(str(form))
|
|
|
+
|
|
|
+ self.assertEqual('\n'.join(form_output), "")
|
|
|
+
|
|
|
+ # test that initial trumps max_num
|
|
|
|
|
|
initial = [
|
|
|
{'name': 'Fernet and Coke'},
|
|
@@ -733,12 +766,13 @@ class FormsFormsetTestCase(TestCase):
|
|
|
|
|
|
for form in formset.forms:
|
|
|
form_output.append(str(form))
|
|
|
-
|
|
|
- self.assertEqual('\n'.join(form_output), "")
|
|
|
+ self.assertEqual('\n'.join(form_output), """<tr><th><label for="id_form-0-name">Name:</label></th><td><input id="id_form-0-name" name="form-0-name" type="text" value="Fernet and Coke" /></td></tr>
|
|
|
+<tr><th><label for="id_form-1-name">Name:</label></th><td><input id="id_form-1-name" name="form-1-name" type="text" value="Bloody Mary" /></td></tr>""")
|
|
|
|
|
|
def test_more_initial_than_max_num(self):
|
|
|
- # More initial forms than max_num will result in only the first max_num of
|
|
|
- # them to be displayed with no extra forms.
|
|
|
+ # More initial forms than max_num now results in all initial forms
|
|
|
+ # being displayed (but no extra forms). This behavior was changed
|
|
|
+ # from max_num taking precedence in the patch for #20084
|
|
|
|
|
|
initial = [
|
|
|
{'name': 'Gin Tonic'},
|
|
@@ -751,9 +785,9 @@ class FormsFormsetTestCase(TestCase):
|
|
|
|
|
|
for form in formset.forms:
|
|
|
form_output.append(str(form))
|
|
|
-
|
|
|
- self.assertHTMLEqual('\n'.join(form_output), """<tr><th><label for="id_form-0-name">Name:</label></th><td><input type="text" name="form-0-name" value="Gin Tonic" id="id_form-0-name" /></td></tr>
|
|
|
-<tr><th><label for="id_form-1-name">Name:</label></th><td><input type="text" name="form-1-name" value="Bloody Mary" id="id_form-1-name" /></td></tr>""")
|
|
|
+ self.assertHTMLEqual('\n'.join(form_output), """<tr><th><label for="id_form-0-name">Name:</label></th><td><input id="id_form-0-name" name="form-0-name" type="text" value="Gin Tonic" /></td></tr>
|
|
|
+<tr><th><label for="id_form-1-name">Name:</label></th><td><input id="id_form-1-name" name="form-1-name" type="text" value="Bloody Mary" /></td></tr>
|
|
|
+<tr><th><label for="id_form-2-name">Name:</label></th><td><input id="id_form-2-name" name="form-2-name" type="text" value="Jack and Coke" /></td></tr>""")
|
|
|
|
|
|
# One form from initial and extra=3 with max_num=2 should result in the one
|
|
|
# initial form and one extra.
|
|
@@ -883,8 +917,8 @@ class FormsFormsetTestCase(TestCase):
|
|
|
# reduce the default limit of 1000 temporarily for testing
|
|
|
_old_DEFAULT_MAX_NUM = formsets.DEFAULT_MAX_NUM
|
|
|
try:
|
|
|
- formsets.DEFAULT_MAX_NUM = 3
|
|
|
- ChoiceFormSet = formset_factory(Choice)
|
|
|
+ formsets.DEFAULT_MAX_NUM = 2
|
|
|
+ ChoiceFormSet = formset_factory(Choice, max_num=1)
|
|
|
# someone fiddles with the mgmt form data...
|
|
|
formset = ChoiceFormSet(
|
|
|
{
|
|
@@ -904,6 +938,8 @@ class FormsFormsetTestCase(TestCase):
|
|
|
)
|
|
|
# But we still only instantiate 3 forms
|
|
|
self.assertEqual(len(formset.forms), 3)
|
|
|
+ # and the formset isn't valid
|
|
|
+ self.assertFalse(formset.is_valid())
|
|
|
finally:
|
|
|
formsets.DEFAULT_MAX_NUM = _old_DEFAULT_MAX_NUM
|
|
|
|
|
@@ -931,7 +967,7 @@ class FormsFormsetTestCase(TestCase):
|
|
|
},
|
|
|
prefix='choices',
|
|
|
)
|
|
|
- # This time four forms are instantiated
|
|
|
+ # Four forms are instantiated and no exception is raised
|
|
|
self.assertEqual(len(formset.forms), 4)
|
|
|
finally:
|
|
|
formsets.DEFAULT_MAX_NUM = _old_DEFAULT_MAX_NUM
|