diff options
| author | Brian Rosner <brosner@gmail.com> | 2008-06-11 03:58:01 +0000 |
|---|---|---|
| committer | Brian Rosner <brosner@gmail.com> | 2008-06-11 03:58:01 +0000 |
| commit | 530670e27f338923c0199dc274f2ecf71af5d762 (patch) | |
| tree | 4ab45d4ccc57c50d7c5bcc1521bc151618444686 /tests | |
| parent | edf396da59d44efebe6d5d7242bda30de4b1afeb (diff) | |
newforms-admin: Fixed #6075 -- Implemented max_num on formsets and model formsets. Added a hook on InlineModelAdmin to customize in the admin interface.
git-svn-id: http://code.djangoproject.com/svn/django/branches/newforms-admin@7613 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/modeltests/model_formsets/models.py | 23 | ||||
| -rw-r--r-- | tests/regressiontests/forms/formsets.py | 75 |
2 files changed, 91 insertions, 7 deletions
diff --git a/tests/modeltests/model_formsets/models.py b/tests/modeltests/model_formsets/models.py index 93bc80ee72..93519a4421 100644 --- a/tests/modeltests/model_formsets/models.py +++ b/tests/modeltests/model_formsets/models.py @@ -31,6 +31,7 @@ __test__ = {'API_TESTS': """ >>> data = { ... 'form-TOTAL_FORMS': '3', # the number of forms rendered ... 'form-INITIAL_FORMS': '0', # the number of forms with initial data +... 'form-MAX_FORMS': '0', # the max number of forms ... 'form-0-name': 'Charles Baudelaire', ... 'form-1-name': 'Arthur Rimbaud', ... 'form-2-name': '', @@ -68,6 +69,7 @@ them in alphabetical order by name. >>> data = { ... 'form-TOTAL_FORMS': '3', # the number of forms rendered ... 'form-INITIAL_FORMS': '2', # the number of forms with initial data +... 'form-MAX_FORMS': '0', # the max number of forms ... 'form-0-id': '2', ... 'form-0-name': 'Arthur Rimbaud', ... 'form-1-id': '1', @@ -111,6 +113,7 @@ deltetion, make sure we don't save that form. >>> data = { ... 'form-TOTAL_FORMS': '4', # the number of forms rendered ... 'form-INITIAL_FORMS': '3', # the number of forms with initial data +... 'form-MAX_FORMS': '0', # the max number of forms ... 'form-0-id': '2', ... 'form-0-name': 'Arthur Rimbaud', ... 'form-1-id': '1', @@ -140,6 +143,7 @@ Let's edit a record to ensure save only returns that one record. >>> data = { ... 'form-TOTAL_FORMS': '4', # the number of forms rendered ... 'form-INITIAL_FORMS': '3', # the number of forms with initial data +... 'form-MAX_FORMS': '0', # the max number of forms ... 'form-0-id': '2', ... 'form-0-name': 'Walt Whitman', ... 'form-1-id': '1', @@ -158,6 +162,22 @@ True >>> formset.save() [<Author: Walt Whitman>] +Test the behavior of max_num with model formsets. It should properly limit +the queryset to reduce the amount of objects being pulled in when not being +used. + +>>> qs = Author.objects.order_by('name') + +>>> AuthorFormSet = modelformset_factory(Author, max_num=2) +>>> formset = AuthorFormSet(queryset=qs) +>>> formset.initial +[{'id': 1, 'name': u'Charles Baudelaire'}, {'id': 3, 'name': u'Paul Verlaine'}] + +>>> AuthorFormSet = modelformset_factory(Author, max_num=3) +>>> formset = AuthorFormSet(queryset=qs) +>>> formset.initial +[{'id': 1, 'name': u'Charles Baudelaire'}, {'id': 3, 'name': u'Paul Verlaine'}, {'id': 2, 'name': u'Walt Whitman'}] + # Inline Formsets ############################################################ We can also create a formset that is tied to a parent model. This is how the @@ -178,6 +198,7 @@ admin system's edit inline functionality works. >>> data = { ... 'book_set-TOTAL_FORMS': '3', # the number of forms rendered ... 'book_set-INITIAL_FORMS': '0', # the number of forms with initial data +... 'book_set-MAX_FORMS': '0', # the max number of forms ... 'book_set-0-title': 'Les Fleurs du Mal', ... 'book_set-1-title': '', ... 'book_set-2-title': '', @@ -212,6 +233,7 @@ book. >>> data = { ... 'book_set-TOTAL_FORMS': '3', # the number of forms rendered ... 'book_set-INITIAL_FORMS': '1', # the number of forms with initial data +... 'book_set-MAX_FORMS': '0', # the max number of forms ... 'book_set-0-id': '1', ... 'book_set-0-title': 'Les Fleurs du Mal', ... 'book_set-1-title': 'Le Spleen de Paris', @@ -238,6 +260,7 @@ This is used in the admin for save_as functionality. >>> data = { ... 'book_set-TOTAL_FORMS': '3', # the number of forms rendered ... 'book_set-INITIAL_FORMS': '2', # the number of forms with initial data +... 'book_set-MAX_FORMS': '0', # the max number of forms ... 'book_set-0-id': '1', ... 'book_set-0-title': 'Les Fleurs du Mal', ... 'book_set-1-id': '2', diff --git a/tests/regressiontests/forms/formsets.py b/tests/regressiontests/forms/formsets.py index 4cccb10d09..dedc0a8e52 100644 --- a/tests/regressiontests/forms/formsets.py +++ b/tests/regressiontests/forms/formsets.py @@ -20,7 +20,7 @@ but we'll look at how to do so later. >>> formset = ChoiceFormSet(auto_id=False, prefix='choices') >>> print formset -<input type="hidden" name="choices-TOTAL_FORMS" value="1" /><input type="hidden" name="choices-INITIAL_FORMS" value="0" /> +<input type="hidden" name="choices-TOTAL_FORMS" value="1" /><input type="hidden" name="choices-INITIAL_FORMS" value="0" /><input type="hidden" name="choices-MAX_FORMS" value="0" /> <tr><th>Choice:</th><td><input type="text" name="choices-0-choice" /></td></tr> <tr><th>Votes:</th><td><input type="text" name="choices-0-votes" /></td></tr> @@ -34,6 +34,7 @@ the TOTAL_FORMS field appropriately. >>> data = { ... 'choices-TOTAL_FORMS': '1', # the number of forms rendered ... 'choices-INITIAL_FORMS': '0', # the number of forms with initial data +... 'choices-MAX_FORMS': '0', # the max number of forms ... 'choices-0-choice': 'Calexico', ... 'choices-0-votes': '100', ... } @@ -60,6 +61,7 @@ any of the forms. >>> data = { ... 'choices-TOTAL_FORMS': '1', # the number of forms rendered ... 'choices-INITIAL_FORMS': '0', # the number of forms with initial data +... 'choices-MAX_FORMS': '0', # the max number of forms ... 'choices-0-choice': 'Calexico', ... 'choices-0-votes': '', ... } @@ -90,6 +92,7 @@ Let's simulate what would happen if we submitted this form. >>> data = { ... 'choices-TOTAL_FORMS': '2', # the number of forms rendered ... 'choices-INITIAL_FORMS': '1', # the number of forms with initial data +... 'choices-MAX_FORMS': '0', # the max number of forms ... 'choices-0-choice': 'Calexico', ... 'choices-0-votes': '100', ... 'choices-1-choice': '', @@ -111,6 +114,7 @@ handle that later. >>> data = { ... 'choices-TOTAL_FORMS': '2', # the number of forms rendered ... 'choices-INITIAL_FORMS': '1', # the number of forms with initial data +... 'choices-MAX_FORMS': '0', # the max number of forms ... 'choices-0-choice': 'Calexico', ... 'choices-0-votes': '100', ... 'choices-1-choice': 'The Decemberists', @@ -130,6 +134,7 @@ handle that case later. >>> data = { ... 'choices-TOTAL_FORMS': '2', # the number of forms rendered ... 'choices-INITIAL_FORMS': '1', # the number of forms with initial data +... 'choices-MAX_FORMS': '0', # the max number of forms ... 'choices-0-choice': '', # deleted value ... 'choices-0-votes': '', # deleted value ... 'choices-1-choice': '', @@ -167,6 +172,7 @@ 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 +... 'choices-MAX_FORMS': '0', # the max number of forms ... 'choices-0-choice': '', ... 'choices-0-votes': '', ... 'choices-1-choice': '', @@ -187,6 +193,7 @@ We can just fill out one of the forms. >>> data = { ... 'choices-TOTAL_FORMS': '3', # the number of forms rendered ... 'choices-INITIAL_FORMS': '0', # the number of forms with initial data +... 'choices-MAX_FORMS': '0', # the max number of forms ... 'choices-0-choice': 'Calexico', ... 'choices-0-votes': '100', ... 'choices-1-choice': '', @@ -207,6 +214,7 @@ And once again, if we try to partially complete a form, validation will fail. >>> data = { ... 'choices-TOTAL_FORMS': '3', # the number of forms rendered ... 'choices-INITIAL_FORMS': '0', # the number of forms with initial data +... 'choices-MAX_FORMS': '0', # the max number of forms ... 'choices-0-choice': 'Calexico', ... 'choices-0-votes': '100', ... 'choices-1-choice': 'The Decemberists', @@ -267,6 +275,7 @@ To delete something, we just need to set that form's special delete field to >>> data = { ... 'choices-TOTAL_FORMS': '3', # the number of forms rendered ... 'choices-INITIAL_FORMS': '2', # the number of forms with initial data +... 'choices-MAX_FORMS': '0', # the max number of forms ... 'choices-0-choice': 'Calexico', ... 'choices-0-votes': '100', ... 'choices-0-DELETE': '', @@ -316,6 +325,7 @@ something at the front of the list, you'd need to set it's order to 0. >>> data = { ... 'choices-TOTAL_FORMS': '3', # the number of forms rendered ... 'choices-INITIAL_FORMS': '2', # the number of forms with initial data +... 'choices-MAX_FORMS': '0', # the max number of forms ... 'choices-0-choice': 'Calexico', ... 'choices-0-votes': '100', ... 'choices-0-ORDER': '1', @@ -342,6 +352,7 @@ they will 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 +... 'choices-MAX_FORMS': '0', # the max number of forms ... 'choices-0-choice': 'Calexico', ... 'choices-0-votes': '100', ... 'choices-0-ORDER': '1', @@ -403,6 +414,7 @@ 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 +... 'choices-MAX_FORMS': '0', # the max number of forms ... 'choices-0-choice': 'Calexico', ... 'choices-0-votes': '100', ... 'choices-0-ORDER': '1', @@ -444,12 +456,7 @@ error if there are any duplicates. ... name = CharField() ... ->>> class FavoriteDrinksFormSet(BaseFormSet): -... form = FavoriteDrinkForm -... extra = 2 -... can_order = False -... can_delete = False -... +>>> class BaseFavoriteDrinksFormSet(BaseFormSet): ... def clean(self): ... seen_drinks = [] ... for drink in self.cleaned_data: @@ -458,11 +465,15 @@ error if there are any duplicates. ... seen_drinks.append(drink['name']) ... +>>> FavoriteDrinksFormSet = formset_factory(FavoriteDrinkForm, +... formset=BaseFavoriteDrinksFormSet, extra=3) + We 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 +... 'drinks-MAX_FORMS': '0', # the max number of forms ... 'drinks-0-name': 'Gin and Tonic', ... 'drinks-1-name': 'Gin and Tonic', ... } @@ -484,6 +495,7 @@ Make sure we didn't break the valid case. >>> data = { ... 'drinks-TOTAL_FORMS': '2', # the number of forms rendered ... 'drinks-INITIAL_FORMS': '0', # the number of forms with initial data +... 'drinks-MAX_FORMS': '0', # the max number of forms ... 'drinks-0-name': 'Gin and Tonic', ... 'drinks-1-name': 'Bloody Mary', ... } @@ -494,6 +506,55 @@ True >>> for error in formset.non_form_errors(): ... print error +# Limiting the maximum number of forms ######################################## + +# Base case for max_num. + +>>> LimitedFavoriteDrinkFormSet = formset_factory(FavoriteDrinkForm, extra=5, max_num=2) +>>> formset = LimitedFavoriteDrinkFormSet() +>>> for form in formset.forms: +... print form +<tr><th><label for="id_form-0-name">Name:</label></th><td><input type="text" name="form-0-name" 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" id="id_form-1-name" /></td></tr> + +# Ensure the that max_num has no affect when extra is less than max_forms. + +>>> LimitedFavoriteDrinkFormSet = formset_factory(FavoriteDrinkForm, extra=1, max_num=2) +>>> formset = LimitedFavoriteDrinkFormSet() +>>> for form in formset.forms: +... print form +<tr><th><label for="id_form-0-name">Name:</label></th><td><input type="text" name="form-0-name" id="id_form-0-name" /></td></tr> + +# max_num with initial data + +# More initial forms than max_num will result in only the first max_num of +# them to be displayed with no extra forms. + +>>> initial = [ +... {'name': 'Gin Tonic'}, +... {'name': 'Bloody Mary'}, +... {'name': 'Jack and Coke'}, +... ] +>>> LimitedFavoriteDrinkFormSet = formset_factory(FavoriteDrinkForm, extra=1, max_num=2) +>>> formset = LimitedFavoriteDrinkFormSet(initial=initial) +>>> for form in formset.forms: +... print form +<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> + +# One form from initial and extra=3 with max_num=2 should result 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) +>>> for form in formset.forms: +... print form +<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" id="id_form-1-name" /></td></tr> + # Regression test for #6926 ################################################## |
