diff --git a/tests/forms_tests/tests/test_formsets.py b/tests/forms_tests/tests/test_formsets.py
index defa46b730..2346a826c2 100644
--- a/tests/forms_tests/tests/test_formsets.py
+++ b/tests/forms_tests/tests/test_formsets.py
@@ -16,8 +16,6 @@ class Choice(Form):
votes = IntegerField()
-# FormSet allows us to use multiple instance of the same form on 1 page. For now,
-# the best way to create a FormSet is by using the formset_factory function.
ChoiceFormSet = formset_factory(Choice)
@@ -36,25 +34,11 @@ class BaseFavoriteDrinksFormSet(BaseFormSet):
seen_drinks.append(drink['name'])
-class EmptyFsetWontValidate(BaseFormSet):
- def clean(self):
- raise ValidationError("Clean method called")
-
-
-# Let's define a FormSet that takes a list of favorite drinks, but raises an
-# error if there are any duplicates. Used in ``test_clean_hook``,
-# ``test_regression_6926`` & ``test_regression_12878``.
+# A FormSet that takes a list of favorite drinks and raises an error if
+# there are any duplicates.
FavoriteDrinksFormSet = formset_factory(FavoriteDrinkForm, formset=BaseFavoriteDrinksFormSet, extra=3)
-# Used in ``test_formset_splitdatetimefield``.
-class SplitDateTimeForm(Form):
- when = SplitDateTimeField(initial=datetime.datetime.now)
-
-
-SplitDateTimeFormSet = formset_factory(SplitDateTimeForm)
-
-
class CustomKwargForm(Form):
def __init__(self, *args, custom_kwarg, **kwargs):
self.custom_kwarg = custom_kwarg
@@ -96,9 +80,10 @@ class FormsFormsetTestCase(SimpleTestCase):
return formset_class(data, **kwargs)
def test_basic_formset(self):
- # A FormSet constructor takes the same arguments as Form. Let's create a FormSet
- # for adding data. By default, it displays 1 blank form. It can display more,
- # but we'll look at how to do so later.
+ """
+ A FormSet constructor takes the same arguments as Form. Create a
+ FormSet for adding data. By default, it displays 1 blank form.
+ """
formset = self.make_choiceformset()
self.assertHTMLEqual(
str(formset),
@@ -109,18 +94,16 @@ class FormsFormsetTestCase(SimpleTestCase):
Choice:
Votes:
"""
)
-
- # We treat FormSet pretty much like we would treat a normal Form. FormSet has an
- # is_valid method, and a cleaned_data or errors attribute depending on whether all
- # the forms passed validation. However, unlike a Form instance, cleaned_data and
- # errors will be a list of dicts rather than just a single dict.
-
+ # FormSet are treated similarly to Forms. FormSet has an is_valid()
+ # method, and a cleaned_data or errors attribute depending on whether
+ # all the forms passed validation. However, unlike a Form, cleaned_data
+ # and errors will be a list of dicts rather than a single dict.
formset = self.make_choiceformset([('Calexico', '100')])
self.assertTrue(formset.is_valid())
self.assertEqual([form.cleaned_data for form in formset.forms], [{'votes': 100, 'choice': 'Calexico'}])
- # If a FormSet was not passed any data, its is_valid and has_changed
- # methods should return False.
+ # If a FormSet wasn't passed any data, is_valid() and has_changed()
+ # return False.
formset = self.make_choiceformset()
self.assertFalse(formset.is_valid())
self.assertFalse(formset.has_changed())
@@ -137,9 +120,7 @@ class FormsFormsetTestCase(SimpleTestCase):
self.assertEqual(form.custom_kwarg, 1)
def test_form_kwargs_formset_dynamic(self):
- """
- Form kwargs can be passed dynamically in a formset.
- """
+ """Form kwargs can be passed dynamically in a formset."""
class DynamicBaseFormSet(BaseFormSet):
def get_form_kwargs(self, index):
return {'custom_kwarg': index}
@@ -190,33 +171,32 @@ class FormsFormsetTestCase(SimpleTestCase):
self.assertEqual(full_clean_counter.call_count, 4)
def test_formset_has_changed(self):
- # FormSet instances has_changed method will be True if any data is
- # passed to his forms, even if the formset didn't validate
+ """
+ FormSet.has_changed() is True if any data is passed to its forms, even
+ if the formset didn't validate.
+ """
blank_formset = self.make_choiceformset([('', '')])
self.assertFalse(blank_formset.has_changed())
-
- # invalid formset test
+ # invalid formset
invalid_formset = self.make_choiceformset([('Calexico', '')])
self.assertFalse(invalid_formset.is_valid())
self.assertTrue(invalid_formset.has_changed())
-
- # valid formset test
+ # valid formset
valid_formset = self.make_choiceformset([('Calexico', '100')])
self.assertTrue(valid_formset.is_valid())
self.assertTrue(valid_formset.has_changed())
def test_formset_initial_data(self):
- # We can also prefill a FormSet with existing data by providing an ``initial``
- # argument to the constructor. ``initial`` should be a list of dicts. By default,
- # an extra blank form is included.
-
+ """
+ A FormSet can be prefilled with existing data by providing a list of
+ dicts to the `initial` argument. By default, an extra blank form is
+ included.
+ """
initial = [{'choice': 'Calexico', 'votes': 100}]
formset = self.make_choiceformset(initial=initial)
form_output = []
-
for form in formset.forms:
form_output.append(form.as_ul())
-
self.assertHTMLEqual(
'\n'.join(form_output),
"""
Choice:
@@ -225,25 +205,26 @@ class FormsFormsetTestCase(SimpleTestCase):
Votes:
"""
)
- # Let's simulate what would happen if we submitted this form.
+ def test_blank_form_unfilled(self):
+ """A form that's displayed as blank may be submitted as blank."""
formset = self.make_choiceformset([('Calexico', '100'), ('', '')], initial_forms=1)
self.assertTrue(formset.is_valid())
self.assertEqual([form.cleaned_data for form in formset.forms], [{'votes': 100, 'choice': 'Calexico'}, {}])
def test_second_form_partially_filled(self):
- # But the second form was blank! Shouldn't we get some errors? No. If we display
- # a form as blank, it's ok for it to be submitted as blank. If we fill out even
- # one of the fields of a blank form though, it will be validated. We may want to
- # required that at least x number of forms are completed, but we'll show how to
- # handle that later.
+ """
+ If at least one field is filled out on a blank form, it will be
+ validated.
+ """
formset = self.make_choiceformset([('Calexico', '100'), ('The Decemberists', '')], initial_forms=1)
self.assertFalse(formset.is_valid())
self.assertEqual(formset.errors, [{}, {'votes': ['This field is required.']}])
def test_delete_prefilled_data(self):
- # If we delete data that was pre-filled, we should get an error. Simply removing
- # data from form fields isn't the proper way to delete it. We'll see how to
- # handle that case later.
+ """
+ Deleting prefilled data is an error. Removing data from form fields
+ isn't the proper way to delete it.
+ """
formset = self.make_choiceformset([('', ''), ('', '')], initial_forms=1)
self.assertFalse(formset.is_valid())
self.assertEqual(
@@ -252,17 +233,15 @@ class FormsFormsetTestCase(SimpleTestCase):
)
def test_displaying_more_than_one_blank_form(self):
- # Displaying more than 1 blank form ###########################################
- # We can also display more than 1 empty form at a time. To do so, pass a
- # extra argument to formset_factory.
+ """
+ More than 1 empty form can be displayed using formset_factory's
+ `extra` argument.
+ """
ChoiceFormSet = formset_factory(Choice, extra=3)
-
formset = ChoiceFormSet(auto_id=False, prefix='choices')
form_output = []
-
for form in formset.forms:
form_output.append(form.as_ul())
-
self.assertHTMLEqual(
'\n'.join(form_output),
"""
Choice:
@@ -272,11 +251,9 @@ class FormsFormsetTestCase(SimpleTestCase):
Choice:
Votes:
"""
)
-
- # Since we displayed every form as blank, we will also accept them back as blank.
- # This may seem a little strange, but later we will show how to require a minimum
- # number of forms to be completed.
-
+ # Since every form was displayed as blank, they are also accepted as
+ # blank. This may seem a little strange, but min_num is used to require
+ # a minimum number of forms to be completed.
data = {
'choices-TOTAL_FORMS': '3', # the number of forms rendered
'choices-INITIAL_FORMS': '0', # the number of forms with initial data
@@ -289,26 +266,23 @@ class FormsFormsetTestCase(SimpleTestCase):
'choices-2-choice': '',
'choices-2-votes': '',
}
-
formset = ChoiceFormSet(data, auto_id=False, prefix='choices')
self.assertTrue(formset.is_valid())
self.assertEqual([form.cleaned_data for form in formset.forms], [{}, {}, {}])
def test_min_num_displaying_more_than_one_blank_form(self):
- # We can also display more than 1 empty form passing min_num argument
- # to formset_factory. It will (essentially) increment the extra argument
+ """"
+ More than 1 empty form can also be displayed using formset_factory's
+ min_num argument. It will (essentially) increment the extra argument.
+ """
ChoiceFormSet = formset_factory(Choice, extra=1, min_num=1)
-
formset = ChoiceFormSet(auto_id=False, prefix='choices')
form_output = []
-
for form in formset.forms:
form_output.append(form.as_ul())
-
# Min_num forms are required; extra forms can be empty.
self.assertFalse(formset.forms[0].empty_permitted)
self.assertTrue(formset.forms[1].empty_permitted)
-
self.assertHTMLEqual(
'\n'.join(form_output),
"""
Choice:
@@ -318,15 +292,12 @@ class FormsFormsetTestCase(SimpleTestCase):
)
def test_min_num_displaying_more_than_one_blank_form_with_zero_extra(self):
- # We can also display more than 1 empty form passing min_num argument
+ """More than 1 empty form can be displayed using min_num."""
ChoiceFormSet = formset_factory(Choice, extra=0, min_num=3)
-
formset = ChoiceFormSet(auto_id=False, prefix='choices')
form_output = []
-
for form in formset.forms:
form_output.append(form.as_ul())
-
self.assertHTMLEqual(
'\n'.join(form_output),
"""
Choice:
@@ -338,8 +309,7 @@ class FormsFormsetTestCase(SimpleTestCase):
)
def test_single_form_completed(self):
- # We can just fill out one of the forms.
-
+ """Just one form may be completed."""
data = {
'choices-TOTAL_FORMS': '3', # the number of forms rendered
'choices-INITIAL_FORMS': '0', # the number of forms with initial data
@@ -352,18 +322,18 @@ class FormsFormsetTestCase(SimpleTestCase):
'choices-2-choice': '',
'choices-2-votes': '',
}
-
ChoiceFormSet = formset_factory(Choice, extra=3)
formset = ChoiceFormSet(data, auto_id=False, prefix='choices')
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)
-
+ """
+ If validate_max is set and max_num is less than TOTAL_FORMS in the
+ data, a ValidationError is raised. 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
@@ -374,18 +344,18 @@ class FormsFormsetTestCase(SimpleTestCase):
'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_formset_validate_min_flag(self):
- # If validate_min is set and min_num is more than TOTAL_FORMS in the
- # data, then throw an exception. MIN_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)
-
+ """
+ If validate_min is set and min_num is more than TOTAL_FORMS in the
+ data, a ValidationError is raised. MIN_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
@@ -396,7 +366,6 @@ class FormsFormsetTestCase(SimpleTestCase):
'choices-1-choice': 'One',
'choices-1-votes': '1',
}
-
ChoiceFormSet = formset_factory(Choice, extra=1, min_num=3, validate_min=True)
formset = ChoiceFormSet(data, auto_id=False, prefix='choices')
self.assertFalse(formset.is_valid())
@@ -439,8 +408,7 @@ class FormsFormsetTestCase(SimpleTestCase):
self.assertEqual(formset.non_form_errors(), ['Please submit 1 or more forms.'])
def test_second_form_partially_filled_2(self):
- # And once again, if we try to partially complete a form, validation will fail.
-
+ """A partially completed form is invalid."""
data = {
'choices-TOTAL_FORMS': '3', # the number of forms rendered
'choices-INITIAL_FORMS': '0', # the number of forms with initial data
@@ -453,23 +421,22 @@ class FormsFormsetTestCase(SimpleTestCase):
'choices-2-choice': '',
'choices-2-votes': '',
}
-
ChoiceFormSet = formset_factory(Choice, extra=3)
formset = ChoiceFormSet(data, auto_id=False, prefix='choices')
self.assertFalse(formset.is_valid())
self.assertEqual(formset.errors, [{}, {'votes': ['This field is required.']}, {}])
def test_more_initial_data(self):
- # The extra argument also works when the formset is pre-filled with initial
- # data.
+ """
+ The extra argument works when the formset is pre-filled with initial
+ data.
+ """
initial = [{'choice': 'Calexico', 'votes': 100}]
ChoiceFormSet = formset_factory(Choice, extra=3)
formset = ChoiceFormSet(initial=initial, auto_id=False, prefix='choices')
form_output = []
-
for form in formset.forms:
form_output.append(form.as_ul())
-
self.assertHTMLEqual(
'\n'.join(form_output),
"""
Choice:
@@ -481,9 +448,7 @@ class FormsFormsetTestCase(SimpleTestCase):
Choice:
Votes:
"""
)
-
- # Make sure retrieving an empty form works, and it shows up in the form list
-
+ # Retrieving an empty form works. Tt shows up in the form list.
self.assertTrue(formset.empty_form.empty_permitted)
self.assertHTMLEqual(
formset.empty_form.as_ul(),
@@ -492,20 +457,17 @@ class FormsFormsetTestCase(SimpleTestCase):
)
def test_formset_with_deletion(self):
- # FormSets with deletion ######################################################
- # We can easily add deletion ability to a FormSet with an argument to
- # formset_factory. This will add a boolean field to each form instance. When
- # that boolean field is True, the form will be in formset.deleted_forms
-
+ """
+ formset_factory's can_delete argument adds a boolean "delete" field to
+ each form. When that boolean field is True, the form will be in
+ formset.deleted_forms.
+ """
ChoiceFormSet = formset_factory(Choice, can_delete=True)
-
initial = [{'choice': 'Calexico', 'votes': 100}, {'choice': 'Fergie', 'votes': 900}]
formset = ChoiceFormSet(initial=initial, auto_id=False, prefix='choices')
form_output = []
-
for form in formset.forms:
form_output.append(form.as_ul())
-
self.assertHTMLEqual(
'\n'.join(form_output),
"""
Choice:
@@ -518,10 +480,8 @@ class FormsFormsetTestCase(SimpleTestCase):
Votes:
Delete:
"""
)
-
- # To delete something, we just need to set that form's special delete field to
- # 'on'. Let's go ahead and delete Fergie.
-
+ # To delete something, set that form's special delete field to 'on'.
+ # Let's go ahead and delete Fergie.
data = {
'choices-TOTAL_FORMS': '3', # the number of forms rendered
'choices-INITIAL_FORMS': '2', # the number of forms with initial data
@@ -537,7 +497,6 @@ class FormsFormsetTestCase(SimpleTestCase):
'choices-2-votes': '',
'choices-2-DELETE': '',
}
-
formset = ChoiceFormSet(data, auto_id=False, prefix='choices')
self.assertTrue(formset.is_valid())
self.assertEqual(
@@ -553,10 +512,12 @@ class FormsFormsetTestCase(SimpleTestCase):
[{'votes': 900, 'DELETE': True, 'choice': 'Fergie'}]
)
- # If we fill a form with something and then we check the can_delete checkbox for
- # that form, that form's errors should not make the entire formset invalid since
- # it's going to be deleted.
-
+ def test_formset_with_deletion_remove_deletion_flag(self):
+ """
+ If a form is filled with something and can_delete is also checked, that
+ form's errors shouldn't make the entire formset invalid since it's
+ going to be deleted.
+ """
class CheckForm(Form):
field = IntegerField(min_value=100)
@@ -575,50 +536,48 @@ class FormsFormsetTestCase(SimpleTestCase):
CheckFormSet = formset_factory(CheckForm, can_delete=True)
formset = CheckFormSet(data, prefix='check')
self.assertTrue(formset.is_valid())
-
- # If we remove the deletion flag now we will have our validation back.
+ # If the deletion flag is removed, validation is enabled.
data['check-1-DELETE'] = ''
formset = CheckFormSet(data, prefix='check')
self.assertFalse(formset.is_valid())
- # Should be able to get deleted_forms from a valid formset even if a
- # deleted form would have been invalid.
-
+ def test_formset_with_deletion_invalid_deleted_form(self):
+ """
+ deleted_forms works on a valid formset even if a deleted form would
+ have been invalid.
+ """
class Person(Form):
name = CharField()
- PeopleForm = formset_factory(
- form=Person,
- can_delete=True)
-
- p = PeopleForm(
- {'form-0-name': '', 'form-0-DELETE': 'on', # no name!
- 'form-TOTAL_FORMS': 1, 'form-INITIAL_FORMS': 1,
- 'form-MIN_NUM_FORMS': 0, 'form-MAX_NUM_FORMS': 1})
-
+ PeopleForm = formset_factory(form=Person, can_delete=True)
+ p = PeopleForm({
+ 'form-0-name': '',
+ 'form-0-DELETE': 'on', # no name!
+ 'form-TOTAL_FORMS': 1,
+ 'form-INITIAL_FORMS': 1,
+ 'form-MIN_NUM_FORMS': 0,
+ 'form-MAX_NUM_FORMS': 1},
+ )
self.assertTrue(p.is_valid())
self.assertEqual(p._errors, [])
self.assertEqual(len(p.deleted_forms), 1)
def test_formsets_with_ordering(self):
- # FormSets with ordering ######################################################
- # We can also add ordering ability to a FormSet with an argument to
- # formset_factory. This will add an integer field to each form instance. When
- # form validation succeeds, [form.cleaned_data for form in formset.forms] will have the data in the correct
- # order specified by the ordering fields. If a number is duplicated in the set
- # of ordering fields, for instance form 0 and form 3 are both marked as 1, then
- # the form index used as a secondary ordering criteria. In order to put
- # something at the front of the list, you'd need to set it's order to 0.
-
+ """
+ formset_factory's can_order argument adds an integer field to each
+ form. When form validation succeeds, [form.cleaned_data for form in formset.forms]
+ will have the data in the correct order specified by the ordering
+ fields. If a number is duplicated in the set of ordering fields, for
+ instance form 0 and form 3 are both marked as 1, then the form index
+ used as a secondary ordering criteria. In order to put something at the
+ front of the list, you'd need to set its order to 0.
+ """
ChoiceFormSet = formset_factory(Choice, can_order=True)
-
initial = [{'choice': 'Calexico', 'votes': 100}, {'choice': 'Fergie', 'votes': 900}]
formset = ChoiceFormSet(initial=initial, auto_id=False, prefix='choices')
form_output = []
-
for form in formset.forms:
form_output.append(form.as_ul())
-
self.assertHTMLEqual(
'\n'.join(form_output),
"""
Choice:
@@ -631,7 +590,6 @@ class FormsFormsetTestCase(SimpleTestCase):
Votes:
Order:
"""
)
-
data = {
'choices-TOTAL_FORMS': '3', # the number of forms rendered
'choices-INITIAL_FORMS': '2', # the number of forms with initial data
@@ -651,10 +609,8 @@ class FormsFormsetTestCase(SimpleTestCase):
formset = ChoiceFormSet(data, auto_id=False, prefix='choices')
self.assertTrue(formset.is_valid())
form_output = []
-
for form in formset.ordered_forms:
form_output.append(form.cleaned_data)
-
self.assertEqual(form_output, [
{'votes': 500, 'ORDER': 0, 'choice': 'The Decemberists'},
{'votes': 100, 'ORDER': 1, 'choice': 'Calexico'},
@@ -662,9 +618,10 @@ class FormsFormsetTestCase(SimpleTestCase):
])
def test_empty_ordered_fields(self):
- # Ordering fields are allowed to be left blank, and if they *are* left blank,
- # they will be sorted below everything else.
-
+ """
+ Ordering fields are allowed to be left blank. If they are left blank,
+ they'll be sorted below everything else.
+ """
data = {
'choices-TOTAL_FORMS': '4', # the number of forms rendered
'choices-INITIAL_FORMS': '3', # the number of forms with initial data
@@ -683,15 +640,12 @@ class FormsFormsetTestCase(SimpleTestCase):
'choices-3-votes': '50',
'choices-3-ORDER': '',
}
-
ChoiceFormSet = formset_factory(Choice, can_order=True)
formset = ChoiceFormSet(data, auto_id=False, prefix='choices')
self.assertTrue(formset.is_valid())
form_output = []
-
for form in formset.ordered_forms:
form_output.append(form.cleaned_data)
-
self.assertEqual(form_output, [
{'votes': 100, 'ORDER': 1, 'choice': 'Calexico'},
{'votes': 900, 'ORDER': 2, 'choice': 'Fergie'},
@@ -700,29 +654,23 @@ class FormsFormsetTestCase(SimpleTestCase):
])
def test_ordering_blank_fieldsets(self):
- # Ordering should work with blank fieldsets.
-
+ """Ordering works with blank fieldsets."""
data = {
'choices-TOTAL_FORMS': '3', # the number of forms rendered
'choices-INITIAL_FORMS': '0', # the number of forms with initial data
'choices-MIN_NUM_FORMS': '0', # min number of forms
'choices-MAX_NUM_FORMS': '0', # max number of forms
}
-
ChoiceFormSet = formset_factory(Choice, can_order=True)
formset = ChoiceFormSet(data, auto_id=False, prefix='choices')
self.assertTrue(formset.is_valid())
form_output = []
-
for form in formset.ordered_forms:
form_output.append(form.cleaned_data)
-
self.assertEqual(form_output, [])
def test_formset_with_ordering_and_deletion(self):
- # FormSets with ordering + deletion ###########################################
- # Let's try throwing ordering and deletion into the same form.
-
+ """FormSets with ordering + deletion."""
ChoiceFormSet = formset_factory(Choice, can_order=True, can_delete=True)
initial = [
@@ -732,10 +680,8 @@ class FormsFormsetTestCase(SimpleTestCase):
]
formset = ChoiceFormSet(initial=initial, auto_id=False, prefix='choices')
form_output = []
-
for form in formset.forms:
form_output.append(form.as_ul())
-
self.assertHTMLEqual(
'\n'.join(form_output),
"""
Choice:
@@ -755,9 +701,7 @@ class FormsFormsetTestCase(SimpleTestCase):
Order:
Delete:
"""
)
-
# Let's delete Fergie, and put The Decemberists ahead of Calexico.
-
data = {
'choices-TOTAL_FORMS': '4', # the number of forms rendered
'choices-INITIAL_FORMS': '3', # the number of forms with initial data
@@ -780,14 +724,11 @@ class FormsFormsetTestCase(SimpleTestCase):
'choices-3-ORDER': '',
'choices-3-DELETE': '',
}
-
formset = ChoiceFormSet(data, auto_id=False, prefix='choices')
self.assertTrue(formset.is_valid())
form_output = []
-
for form in formset.ordered_forms:
form_output.append(form.cleaned_data)
-
self.assertEqual(form_output, [
{'votes': 500, 'DELETE': False, 'ORDER': 0, 'choice': 'The Decemberists'},
{'votes': 100, 'DELETE': False, 'ORDER': 1, 'choice': 'Calexico'},
@@ -798,14 +739,14 @@ class FormsFormsetTestCase(SimpleTestCase):
)
def test_invalid_deleted_form_with_ordering(self):
- # Should be able to get ordered forms from a valid formset even if a
- # deleted form would have been invalid.
-
+ """
+ Can get ordered_forms from a valid formset even if a deleted form
+ would have been invalid.
+ """
class Person(Form):
name = CharField()
PeopleForm = formset_factory(form=Person, can_delete=True, can_order=True)
-
p = PeopleForm({
'form-0-name': '',
'form-0-DELETE': 'on', # no name!
@@ -814,17 +755,15 @@ class FormsFormsetTestCase(SimpleTestCase):
'form-MIN_NUM_FORMS': 0,
'form-MAX_NUM_FORMS': 1
})
-
self.assertTrue(p.is_valid())
self.assertEqual(p.ordered_forms, [])
def test_clean_hook(self):
- # FormSet clean hook ##########################################################
- # FormSets have a hook for doing extra validation that shouldn't be tied to any
- # particular form. It follows the same pattern as the clean hook on Forms.
-
- # We start out with a some duplicate data.
-
+ """
+ FormSets have a clean() hook for doing extra validation that isn't tied
+ to any form. It follows the same pattern as the clean() hook on Forms.
+ """
+ # Start out with a some duplicate data.
data = {
'drinks-TOTAL_FORMS': '2', # the number of forms rendered
'drinks-INITIAL_FORMS': '0', # the number of forms with initial data
@@ -833,18 +772,13 @@ class FormsFormsetTestCase(SimpleTestCase):
'drinks-0-name': 'Gin and Tonic',
'drinks-1-name': 'Gin and Tonic',
}
-
formset = FavoriteDrinksFormSet(data, prefix='drinks')
self.assertFalse(formset.is_valid())
-
# Any errors raised by formset.clean() are available via the
# formset.non_form_errors() method.
-
for error in formset.non_form_errors():
self.assertEqual(str(error), 'You may only specify a drink once.')
-
- # Make sure we didn't break the valid case.
-
+ # The valid case still works.
data = {
'drinks-TOTAL_FORMS': '2', # the number of forms rendered
'drinks-INITIAL_FORMS': '0', # the number of forms with initial data
@@ -853,25 +787,19 @@ class FormsFormsetTestCase(SimpleTestCase):
'drinks-0-name': 'Gin and Tonic',
'drinks-1-name': 'Bloody Mary',
}
-
formset = FavoriteDrinksFormSet(data, prefix='drinks')
self.assertTrue(formset.is_valid())
self.assertEqual(formset.non_form_errors(), [])
def test_limiting_max_forms(self):
- # Limiting the maximum number of forms ########################################
- # Base case for max_num.
-
+ """Limiting the maximum number of forms with max_num."""
# When not passed, max_num will take a high default value, leaving the
# number of forms only controlled by the value of the extra parameter.
-
LimitedFavoriteDrinkFormSet = formset_factory(FavoriteDrinkForm, extra=3)
formset = LimitedFavoriteDrinkFormSet()
form_output = []
-
for form in formset.forms:
form_output.append(str(form))
-
self.assertHTMLEqual(
'\n'.join(form_output),
"""
@@ -881,24 +809,20 @@ class FormsFormsetTestCase(SimpleTestCase):
"""
)
-
# If max_num is 0 then no form is rendered at all.
LimitedFavoriteDrinkFormSet = formset_factory(FavoriteDrinkForm, extra=3, max_num=0)
formset = LimitedFavoriteDrinkFormSet()
form_output = []
-
for form in formset.forms:
form_output.append(str(form))
-
self.assertEqual('\n'.join(form_output), "")
+ def test_limited_max_forms_two(self):
LimitedFavoriteDrinkFormSet = formset_factory(FavoriteDrinkForm, extra=5, max_num=2)
formset = LimitedFavoriteDrinkFormSet()
form_output = []
-
for form in formset.forms:
form_output.append(str(form))
-
self.assertHTMLEqual(
'\n'.join(form_output),
"""
@@ -907,14 +831,13 @@ class FormsFormsetTestCase(SimpleTestCase):
"""
)
- # max_num has no effect when extra is less than max_num.
+ def test_limiting_extra_lest_than_max_num(self):
+ """max_num has no effect when extra is less than max_num."""
LimitedFavoriteDrinkFormSet = formset_factory(FavoriteDrinkForm, extra=1, max_num=2)
formset = LimitedFavoriteDrinkFormSet()
form_output = []
-
for form in formset.forms:
form_output.append(str(form))
-
self.assertHTMLEqual(
'\n'.join(form_output),
"""
@@ -922,22 +845,18 @@ class FormsFormsetTestCase(SimpleTestCase):
)
def test_max_num_with_initial_data(self):
- # max_num with initial data
-
+ """max_num with initial data."""
# When not passed, max_num will take a high default value, leaving the
# number of forms only controlled by the value of the initial and extra
# parameters.
-
initial = [
{'name': 'Fernet and Coke'},
]
LimitedFavoriteDrinkFormSet = formset_factory(FavoriteDrinkForm, extra=1)
formset = LimitedFavoriteDrinkFormSet(initial=initial)
form_output = []
-
for form in formset.forms:
form_output.append(str(form))
-
self.assertHTMLEqual(
'\n'.join(form_output),
"""
@@ -947,21 +866,19 @@ class FormsFormsetTestCase(SimpleTestCase):
)
def test_max_num_zero(self):
- # 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)
-
+ """
+ If max_num is 0 then no form is rendered at all, regardless of extra,
+ unless initial data is present.
+ """
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
-
+ def test_max_num_zero_with_initial(self):
+ # initial trumps max_num
initial = [
{'name': 'Fernet and Coke'},
{'name': 'Bloody Mary'},
@@ -969,7 +886,6 @@ class FormsFormsetTestCase(SimpleTestCase):
LimitedFavoriteDrinkFormSet = formset_factory(FavoriteDrinkForm, extra=1, max_num=0)
formset = LimitedFavoriteDrinkFormSet(initial=initial)
form_output = []
-
for form in formset.forms:
form_output.append(str(form))
self.assertHTMLEqual(
@@ -981,10 +897,10 @@ class FormsFormsetTestCase(SimpleTestCase):
)
def test_more_initial_than_max_num(self):
- # 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
-
+ """
+ More initial forms than max_num results in all initial forms being
+ displayed (but no extra forms).
+ """
initial = [
{'name': 'Gin Tonic'},
{'name': 'Bloody Mary'},
@@ -993,7 +909,6 @@ class FormsFormsetTestCase(SimpleTestCase):
LimitedFavoriteDrinkFormSet = formset_factory(FavoriteDrinkForm, extra=1, max_num=2)
formset = LimitedFavoriteDrinkFormSet(initial=initial)
form_output = []
-
for form in formset.forms:
form_output.append(str(form))
self.assertHTMLEqual(
@@ -1006,18 +921,19 @@ class FormsFormsetTestCase(SimpleTestCase):
"""
)
- # One form from initial and extra=3 with max_num=2 should result in the one
- # initial form and one extra.
+ def test_more_initial_form_result_in_one(self):
+ """
+ One form from initial and extra=3 with max_num=2 results in the one
+ initial form and one extra.
+ """
initial = [
{'name': 'Gin Tonic'},
]
LimitedFavoriteDrinkFormSet = formset_factory(FavoriteDrinkForm, extra=3, max_num=2)
formset = LimitedFavoriteDrinkFormSet(initial=initial)
form_output = []
-
for form in formset.forms:
form_output.append(str(form))
-
self.assertHTMLEqual(
'\n'.join(form_output),
"""
@@ -1026,13 +942,10 @@ class FormsFormsetTestCase(SimpleTestCase):
"""
)
- def test_regression_6926(self):
- # Regression test for #6926 ##################################################
- # Make sure the management form has the correct prefix.
-
+ def test_management_form_prefix(self):
+ """The management form has the correct prefix."""
formset = FavoriteDrinksFormSet()
self.assertEqual(formset.management_form.prefix, 'form')
-
data = {
'form-TOTAL_FORMS': '2',
'form-INITIAL_FORMS': '0',
@@ -1041,13 +954,10 @@ class FormsFormsetTestCase(SimpleTestCase):
}
formset = FavoriteDrinksFormSet(data=data)
self.assertEqual(formset.management_form.prefix, 'form')
-
formset = FavoriteDrinksFormSet(initial={})
self.assertEqual(formset.management_form.prefix, 'form')
- def test_regression_12878(self):
- # Regression test for #12878 #################################################
-
+ def test_non_form_errors(self):
data = {
'drinks-TOTAL_FORMS': '2', # the number of forms rendered
'drinks-INITIAL_FORMS': '0', # the number of forms with initial data
@@ -1056,22 +966,19 @@ class FormsFormsetTestCase(SimpleTestCase):
'drinks-0-name': 'Gin and Tonic',
'drinks-1-name': 'Gin and Tonic',
}
-
formset = FavoriteDrinksFormSet(data, prefix='drinks')
self.assertFalse(formset.is_valid())
self.assertEqual(formset.non_form_errors(), ['You may only specify a drink once.'])
def test_formset_iteration(self):
- # Regression tests for #16455 -- formset instances are iterable
+ """Formset instances are iterable."""
ChoiceFormset = formset_factory(Choice, extra=3)
formset = ChoiceFormset()
-
- # confirm iterated formset yields formset.forms
+ # An iterated formset yields formset.forms.
forms = list(formset)
self.assertEqual(forms, formset.forms)
self.assertEqual(len(formset), len(forms))
-
- # confirm indexing of formset
+ # A formset may be indexed to retrieve its forms.
self.assertEqual(formset[0], forms[0])
with self.assertRaises(IndexError):
formset[3]
@@ -1086,18 +993,14 @@ class FormsFormsetTestCase(SimpleTestCase):
ReverseChoiceFormset = formset_factory(Choice, BaseReverseFormSet, extra=3)
reverse_formset = ReverseChoiceFormset()
-
- # confirm that __iter__ modifies rendering order
- # compare forms from "reverse" formset with forms from original formset
+ # __iter__() modifies the rendering order.
+ # Compare forms from "reverse" formset with forms from original formset
self.assertEqual(str(reverse_formset[0]), str(forms[-1]))
self.assertEqual(str(reverse_formset[1]), str(forms[-2]))
self.assertEqual(len(reverse_formset), len(forms))
def test_formset_nonzero(self):
- """
- Formsets with no forms should still evaluate as true.
- Regression test for #15722
- """
+ """A formsets without any forms evaluates as True."""
ChoiceFormset = formset_factory(Choice, extra=0)
formset = ChoiceFormset()
self.assertEqual(len(formset.forms), 0)
@@ -1105,9 +1008,12 @@ class FormsFormsetTestCase(SimpleTestCase):
def test_formset_splitdatetimefield(self):
"""
- Formset should also work with SplitDateTimeField(initial=datetime.datetime.now).
- Regression test for #18709.
+ Formset works with SplitDateTimeField(initial=datetime.datetime.now).
"""
+ class SplitDateTimeForm(Form):
+ when = SplitDateTimeField(initial=datetime.datetime.now)
+
+ SplitDateTimeFormSet = formset_factory(SplitDateTimeForm)
data = {
'form-TOTAL_FORMS': '1',
'form-INITIAL_FORMS': '0',
@@ -1118,7 +1024,7 @@ class FormsFormsetTestCase(SimpleTestCase):
self.assertTrue(formset.is_valid())
def test_formset_error_class(self):
- # Regression tests for #16479 -- formsets form use ErrorList instead of supplied error_class
+ """Formset's forms use the formset's error_class."""
class CustomErrorList(ErrorList):
pass
@@ -1126,9 +1032,7 @@ class FormsFormsetTestCase(SimpleTestCase):
self.assertEqual(formset.forms[0].error_class, CustomErrorList)
def test_formset_calls_forms_is_valid(self):
- # Regression tests for #18574 -- make sure formsets call
- # is_valid() on each form.
-
+ """Formsets call is_valid() on each form."""
class AnotherChoice(Choice):
def is_valid(self):
self.is_valid_called = True
@@ -1210,9 +1114,10 @@ class FormsFormsetTestCase(SimpleTestCase):
formsets.DEFAULT_MAX_NUM = _old_DEFAULT_MAX_NUM
def test_non_form_errors_run_full_clean(self):
- # Regression test for #11160
- # If non_form_errors() is called without calling is_valid() first,
- # it should ensure that full_clean() is called.
+ """
+ If non_form_errors() is called without calling is_valid() first,
+ it should ensure that full_clean() is called.
+ """
class BaseCustomFormSet(BaseFormSet):
def clean(self):
raise ValidationError("This is a non-form error")
@@ -1235,8 +1140,7 @@ class FormsFormsetTestCase(SimpleTestCase):
'check-1-field': '50',
'check-1-DELETE': 'on',
}
- CheckFormSet = formset_factory(CheckForm, max_num=1, validate_max=True,
- can_delete=True)
+ CheckFormSet = formset_factory(CheckForm, max_num=1, validate_max=True, can_delete=True)
formset = CheckFormSet(data, prefix='check')
self.assertTrue(formset.is_valid())
@@ -1249,7 +1153,6 @@ class FormsFormsetTestCase(SimpleTestCase):
([('Calexico', '100'), ('Calexico', '')], 1),
([('Calexico', ''), ('Calexico', '')], 2),
]
-
for formset_data, expected_error_count in data:
formset = self.make_choiceformset(formset_data)
self.assertEqual(formset.total_error_count(), expected_error_count)
@@ -1264,11 +1167,9 @@ class FormsFormsetTestCase(SimpleTestCase):
'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.assertEqual(formset.total_error_count(), 1)
-
data['choices-1-votes'] = ''
formset = ChoiceFormSet(data, auto_id=False, prefix='choices')
self.assertEqual(formset.total_error_count(), 2)
@@ -1327,7 +1228,6 @@ class FormsetAsFooTests(SimpleTestCase):
)
-# Regression test for #11418 #################################################
class ArticleForm(Form):
title = CharField()
pub_date = DateField()
@@ -1378,16 +1278,13 @@ class TestIsBoundBehavior(SimpleTestCase):
}
unbound_formset = ArticleFormSet()
bound_formset = ArticleFormSet(data)
-
empty_forms = [
unbound_formset.empty_form,
bound_formset.empty_form
]
-
# Empty forms should be unbound
self.assertFalse(empty_forms[0].is_bound)
self.assertFalse(empty_forms[1].is_bound)
-
# The empty forms should be equal.
self.assertHTMLEqual(empty_forms[0].as_p(), empty_forms[1].as_p())
@@ -1395,6 +1292,10 @@ class TestIsBoundBehavior(SimpleTestCase):
class TestEmptyFormSet(SimpleTestCase):
def test_empty_formset_is_valid(self):
"""An empty formset still calls clean()"""
+ class EmptyFsetWontValidate(BaseFormSet):
+ def clean(self):
+ raise ValidationError('Clean method called')
+
EmptyFsetWontValidateFormset = formset_factory(FavoriteDrinkForm, extra=0, formset=EmptyFsetWontValidate)
formset = EmptyFsetWontValidateFormset(
data={'form-INITIAL_FORMS': '0', 'form-TOTAL_FORMS': '0'},
@@ -1408,14 +1309,14 @@ class TestEmptyFormSet(SimpleTestCase):
self.assertFalse(formset2.is_valid())
def test_empty_formset_media(self):
- """Make sure media is available on empty formset, refs #19545"""
+ """Media is available on empty formset."""
class MediaForm(Form):
class Media:
js = ('some-file.js',)
self.assertIn('some-file.js', str(formset_factory(MediaForm, extra=0)().media))
def test_empty_formset_is_multipart(self):
- """Make sure `is_multipart()` works with empty formset, refs #19545"""
+ """is_multipart() works with an empty formset."""
class FileForm(Form):
file = FileField()
self.assertTrue(formset_factory(FileForm, extra=0)().is_multipart())