diff --git a/AUTHORS b/AUTHORS index 94bd91e9067..8367420fdfa 100644 --- a/AUTHORS +++ b/AUTHORS @@ -357,6 +357,7 @@ answer newbie questions, and generally made Django that much better: ricardojbarrios@gmail.com Mike Richardson Matt Riggott + Alex Robbins Henrique Romano Armin Ronacher Daniel Roseman diff --git a/django/contrib/contenttypes/generic.py b/django/contrib/contenttypes/generic.py index 9fd2550185a..55645481331 100644 --- a/django/contrib/contenttypes/generic.py +++ b/django/contrib/contenttypes/generic.py @@ -389,6 +389,8 @@ class GenericInlineModelAdmin(InlineModelAdmin): "can_delete": True, "can_order": False, "fields": fields, + "max_num": self.max_num, + "exclude": self.exclude } return generic_inlineformset_factory(self.model, **defaults) diff --git a/tests/regressiontests/generic_inline_admin/models.py b/tests/regressiontests/generic_inline_admin/models.py index 6e9fbebabb6..bc6764d8b2d 100644 --- a/tests/regressiontests/generic_inline_admin/models.py +++ b/tests/regressiontests/generic_inline_admin/models.py @@ -20,11 +20,55 @@ class Media(models.Model): class MediaInline(generic.GenericTabularInline): model = Media - extra = 1 class EpisodeAdmin(admin.ModelAdmin): inlines = [ MediaInline, ] - admin.site.register(Episode, EpisodeAdmin) + +# +# These models let us test the different GenericInline settings at +# different urls in the admin site. +# + +# +# Generic inline with extra = 0 +# + +class EpisodeExtra(Episode): + pass + +class MediaExtraInline(generic.GenericTabularInline): + model = Media + extra = 0 + +admin.site.register(EpisodeExtra, inlines=[MediaExtraInline]) + +# +# Generic inline with extra and max_num +# + +class EpisodeMaxNum(Episode): + pass + +class MediaMaxNumInline(generic.GenericTabularInline): + model = Media + extra = 5 + max_num = 2 + +admin.site.register(EpisodeMaxNum, inlines=[MediaMaxNumInline]) + +# +# Generic inline with exclude +# + +class EpisodeExclude(Episode): + pass + +class MediaExcludeInline(generic.GenericTabularInline): + model = Media + exclude = ['url'] + +admin.site.register(EpisodeExclude, inlines=[MediaExcludeInline]) + diff --git a/tests/regressiontests/generic_inline_admin/tests.py b/tests/regressiontests/generic_inline_admin/tests.py index 19eab52ae02..10c86aebfd5 100644 --- a/tests/regressiontests/generic_inline_admin/tests.py +++ b/tests/regressiontests/generic_inline_admin/tests.py @@ -5,7 +5,7 @@ from django.conf import settings from django.contrib.contenttypes.generic import generic_inlineformset_factory # local test models -from models import Episode, Media +from models import Episode, EpisodeExtra, EpisodeMaxNum, EpisodeExclude, Media class GenericAdminViewTest(TestCase): fixtures = ['users.xml'] @@ -80,3 +80,62 @@ class GenericAdminViewTest(TestCase): # Regression test for #10522. inline_formset = generic_inlineformset_factory(Media, exclude=('url',)) + +class GenericInlineAdminParametersTest(TestCase): + fixtures = ['users.xml'] + + def setUp(self): + self.client.login(username='super', password='secret') + + # Can't load content via a fixture (since the GenericForeignKey + # relies on content type IDs, which will vary depending on what + # other tests have been run), thus we do it here. + test_classes = [ + Episode, + EpisodeExtra, + EpisodeMaxNum, + EpisodeExclude, + ] + for klass in test_classes: + e = klass.objects.create(name='This Week in Django') + m = Media(content_object=e, url='http://example.com/podcast.mp3') + m.save() + + def tearDown(self): + self.client.logout() + + def testNoParam(self): + """ + With one initial form, extra (default) at 3, there should be 4 forms. + """ + response = self.client.get('/generic_inline_admin/admin/generic_inline_admin/episode/1/') + formset = response.context['inline_admin_formsets'][0].formset + self.assertEqual(formset.total_form_count(), 4) + self.assertEqual(formset.initial_form_count(), 1) + + def testExtraParam(self): + """ + With extra=0, there should be one form. + """ + response = self.client.get('/generic_inline_admin/admin/generic_inline_admin/episodeextra/2/') + formset = response.context['inline_admin_formsets'][0].formset + self.assertEqual(formset.total_form_count(), 1) + self.assertEqual(formset.initial_form_count(), 1) + + def testMaxNumParam(self): + """ + With extra=5 and max_num=2, there should be only 2 forms. + """ + inline_form_data = '' + response = self.client.get('/generic_inline_admin/admin/generic_inline_admin/episodemaxnum/3/') + formset = response.context['inline_admin_formsets'][0].formset + self.assertEqual(formset.total_form_count(), 2) + self.assertEqual(formset.initial_form_count(), 1) + + def testExcludeParam(self): + """ + Generic inline formsets should respect include. + """ + response = self.client.get('/generic_inline_admin/admin/generic_inline_admin/episodeexclude/4/') + formset = response.context['inline_admin_formsets'][0].formset + self.failIf('url' in formset.forms[0], 'The formset has excluded "url" field.') \ No newline at end of file