From e4447e69ab990f92d1d3653b03c9669055ffd8cb Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Thu, 10 Mar 2022 15:42:40 +0000 Subject: [PATCH] Omitting both the formsets and exclude_formsets arguments should result in no formsets, rather than all formsets --- modelcluster/forms.py | 10 ++- tests/tests/test_cluster_form.py | 128 ++++++++++++++++++++----------- tests/tests/test_formset.py | 8 +- 3 files changed, 97 insertions(+), 49 deletions(-) diff --git a/modelcluster/forms.py b/modelcluster/forms.py index f8dca46..4eee2a2 100644 --- a/modelcluster/forms.py +++ b/modelcluster/forms.py @@ -265,6 +265,7 @@ def __new__(cls, name, bases, attrs): opts = new_class._meta = ClusterFormOptions(getattr(new_class, 'Meta', None)) if opts.model: formsets = {} + for rel in get_all_child_relations(opts.model): # to build a childformset class from this relation, we need to specify: # - the base model (opts.model) @@ -274,9 +275,14 @@ def __new__(cls, name, bases, attrs): rel_name = rel.get_accessor_name() # apply 'formsets' and 'exclude_formsets' rules from meta - if opts.formsets is not None and rel_name not in opts.formsets: + if opts.exclude_formsets is not None and rel_name in opts.exclude_formsets: + # formset is explicitly excluded + continue + elif opts.formsets is not None and rel_name not in opts.formsets: + # a formset list has been specified and this isn't on it continue - if opts.exclude_formsets and rel_name in opts.exclude_formsets: + elif opts.formsets is None and opts.exclude_formsets is None: + # neither formsets nor exclude_formsets has been specified - no formsets at all continue try: diff --git a/tests/tests/test_cluster_form.py b/tests/tests/test_cluster_form.py index f367373..6de315d 100644 --- a/tests/tests/test_cluster_form.py +++ b/tests/tests/test_cluster_form.py @@ -15,11 +15,27 @@ class ClusterFormTest(TestCase): + def test_cluster_form_with_no_formsets(self): + class BandForm(ClusterForm): + class Meta: + model = Band + fields = ['name'] + + self.assertFalse(BandForm.formsets) + + beatles = Band(name='The Beatles') + form = BandForm(instance=beatles) + form_html = form.as_p() + self.assertIsInstance(form_html, SafeString) + self.assertInHTML('', form_html) + self.assertInHTML('', form_html, count=0) + def test_cluster_form(self): class BandForm(ClusterForm): class Meta: model = Band fields = ['name'] + formsets = ['members', 'albums'] self.assertTrue(BandForm.formsets) @@ -33,6 +49,7 @@ class Meta: self.assertEqual(5, len(form.formsets['members'].forms)) form_html = form.as_p() self.assertIsInstance(form_html, SafeString) + self.assertInHTML('', form_html) self.assertInHTML('', form_html) def test_empty_cluster_form(self): @@ -40,6 +57,7 @@ class BandForm(ClusterForm): class Meta: model = Band fields = ['name'] + formsets = ['members', 'albums'] form = BandForm() @@ -50,6 +68,7 @@ class BandForm(ClusterForm): class Meta: model = Band fields = ['name'] + formsets = ['members', 'albums'] beatles = Band(name='The Beatles', members=[ BandMember(name='George Harrison'), @@ -133,6 +152,7 @@ class Meta: } } fields = ['name'] + formsets = ['members', 'albums'] form = BandForm() self.assertEqual(Textarea, type(form['name'].field.widget)) @@ -250,6 +270,7 @@ class BandFormWithFFC(ClusterForm): class Meta: model = Band fields = ['name'] + formsets = ['members', 'albums'] form = BandFormWithFFC() self.assertEqual(Textarea, type(form['name'].field.widget)) @@ -260,6 +281,7 @@ class BandForm(ClusterForm): class Meta: model = Band fields = ['name'] + formsets = ['members', 'albums'] john = BandMember(name='John Lennon') paul = BandMember(name='Paul McCartney') @@ -300,48 +322,6 @@ class Meta: self.assertTrue(BandMember.objects.filter(name='George Harrison').exists()) self.assertFalse(BandMember.objects.filter(name='John Lennon').exists()) - def test_can_omit_formset_from_submission(self): - """ - If no explicit `formsets` parameter has been given, any formsets missing from the - submission should be skipped over. - https://github.com/wagtail/wagtail/issues/5414#issuecomment-567468127 - """ - class BandForm(ClusterForm): - class Meta: - model = Band - fields = ['name'] - - john = BandMember(name='John Lennon') - paul = BandMember(name='Paul McCartney') - abbey_road = Album(name='Abbey Road') - beatles = Band(name='The Beatles', members=[john, paul], albums=[abbey_road]) - beatles.save() - - form = BandForm({ - 'name': "The Beatles", - - 'members-TOTAL_FORMS': 3, - 'members-INITIAL_FORMS': 2, - 'members-MAX_NUM_FORMS': 1000, - - 'members-0-name': john.name, - 'members-0-DELETE': 'members-0-DELETE', - 'members-0-id': john.id, - - 'members-1-name': paul.name, - 'members-1-id': paul.id, - - 'members-2-name': 'George Harrison', - 'members-2-id': '', - }, instance=beatles) - self.assertTrue(form.is_valid()) - form.save() - - beatles = Band.objects.get(id=beatles.id) - self.assertEqual(1, beatles.albums.count()) - self.assertTrue(BandMember.objects.filter(name='George Harrison').exists()) - self.assertFalse(BandMember.objects.filter(name='John Lennon').exists()) - def test_cannot_omit_explicit_formset_from_submission(self): """ If an explicit `formsets` parameter has been given, formsets missing from a form submission @@ -389,6 +369,7 @@ class BandForm(ClusterForm): class Meta: model = Band fields = ['name'] + formsets = ['members', 'albums'] john = BandMember(name='John Lennon') paul = BandMember(name='Paul McCartney') @@ -435,6 +416,7 @@ class BandForm(ClusterForm): class Meta: model = Band fields = ['name'] + formsets = ['members', 'albums'] form = BandForm({ 'name': "The Beatles", @@ -475,6 +457,7 @@ class BandForm(ClusterForm): class Meta: model = Band fields = ['name'] + formsets = ['members', 'albums'] form = BandForm() form_html = form.as_p() @@ -486,6 +469,7 @@ class BandForm(ClusterForm): class Meta: model = Band fields = ['name'] + formsets = ['members', 'albums'] form = BandForm({ 'name': "The Beatles", @@ -525,6 +509,7 @@ class BandForm(ClusterForm): class Meta: model = Band fields = ['name'] + formsets = ['members', 'albums'] please_please_me = Album(name='Please Please Me', release_date=datetime.date(1963, 3, 22)) beatles = Band(name='The Beatles', albums=[please_please_me]) @@ -582,7 +567,7 @@ class Meta: beatles.save() self.assertEqual(0, Band.objects.get(id=beatles.id).albums.count()) - def test_cluster_form_without_formsets(self): + def test_cluster_form_with_empty_formsets_list(self): class BandForm(ClusterForm): class Meta: model = Band @@ -609,6 +594,7 @@ class RestaurantForm(ClusterForm): class Meta: model = Restaurant fields = ['name', 'tags', 'serves_hot_dogs', 'proprietor'] + formsets = ['menu_items', 'reviews', 'tagged_items'] self.assertIn('reviews', RestaurantForm.formsets) @@ -678,6 +664,7 @@ class FormWithWidgetMedia(ClusterForm): class Meta: model = Restaurant fields = ['name', 'tags', 'serves_hot_dogs', 'proprietor'] + formsets = ['menu_items', 'reviews', 'tagged_items'] widgets = { 'name': WidgetWithMedia } @@ -760,6 +747,7 @@ class BandForm(ClusterForm): class Meta: model = Band fields = ['name'] + formsets = ['members', 'albums'] form = BandForm({ 'name': "The Beatles", @@ -861,11 +849,37 @@ class Meta: class NestedClusterFormTest(TestCase): + def test_no_nested_formsets_without_explicit_formset_definition(self): + class BandForm(ClusterForm): + class Meta: + model = Band + fields = ['name'] + formsets=['members', 'albums'] + + self.assertTrue(BandForm.formsets) + + beatles = Band(name='The Beatles', albums=[ + Album(name='Please Please Me', songs=[ + Song(name='I Saw Her Standing There'), + Song(name='Misery') + ]), + ]) + + form = BandForm(instance=beatles) + + self.assertEqual(4, len(form.formsets['albums'].forms)) + self.assertNotIn('songs', form.formsets['albums'].forms[0].formsets) + self.assertNotIn('songs', form.as_p()) + def test_nested_formsets(self): class BandForm(ClusterForm): class Meta: model = Band fields = ['name'] + formsets={ + 'members': [], + 'albums': {'formsets': ['songs']} + } self.assertTrue(BandForm.formsets) @@ -887,6 +901,10 @@ class BandForm(ClusterForm): class Meta: model = Band fields = ['name'] + formsets={ + 'members': [], + 'albums': {'formsets': ['songs']} + } form = BandForm() self.assertEqual(3, len(form.formsets['albums'].forms)) @@ -897,6 +915,10 @@ class BandForm(ClusterForm): class Meta: model = Band fields = ['name'] + formsets={ + 'members': [], + 'albums': {'formsets': ['songs']} + } beatles = Band(name='The Beatles', albums=[ Album(name='Please Please Me', songs=[ @@ -987,6 +1009,10 @@ class BandForm(ClusterForm): class Meta: model = Band fields = ['name'] + formsets={ + 'members': [], + 'albums': {'formsets': ['songs']} + } first_song = Song(name='I Saw Her Standing There') second_song = Song(name='Misery') @@ -1042,6 +1068,10 @@ class BandForm(ClusterForm): class Meta: model = Band fields = ['name'] + formsets={ + 'members': [], + 'albums': {'formsets': ['songs']} + } first_song = Song(name='I Saw Her Standing There') second_song = Song(name='Misery') @@ -1095,6 +1125,10 @@ class BandForm(ClusterForm): class Meta: model = Band fields = ['name'] + formsets={ + 'members': [], + 'albums': {'formsets': ['songs']} + } form = BandForm({ 'name': "The Beatles", @@ -1144,6 +1178,10 @@ class BandForm(ClusterForm): class Meta: model = Band fields = ['name'] + formsets={ + 'members': [], + 'albums': {'formsets': ['songs']} + } form = BandForm() form_html = form.as_p() @@ -1155,6 +1193,10 @@ class BandForm(ClusterForm): class Meta: model = Band fields = ['name'] + formsets={ + 'members': [], + 'albums': {'formsets': ['songs']} + } form = BandForm({ 'name': "The Beatles", diff --git a/tests/tests/test_formset.py b/tests/tests/test_formset.py index 103754d..851127c 100644 --- a/tests/tests/test_formset.py +++ b/tests/tests/test_formset.py @@ -467,7 +467,7 @@ def test_can_create_formset(self): Song(name='Misery') ]) ]) - AlbumsFormset = childformset_factory(Band, Album, form=ClusterForm, extra=3) + AlbumsFormset = childformset_factory(Band, Album, form=ClusterForm, formsets=['songs'], extra=3) albums_formset = AlbumsFormset(instance=beatles) self.assertEqual(4, len(albums_formset.forms)) @@ -480,7 +480,7 @@ def test_can_create_formset(self): ) def test_empty_formset(self): - AlbumsFormset = childformset_factory(Band, Album, form=ClusterForm, extra=3) + AlbumsFormset = childformset_factory(Band, Album, form=ClusterForm, formsets=['songs'], extra=3) albums_formset = AlbumsFormset() self.assertEqual(3, len(albums_formset.forms)) self.assertEqual(3, len(albums_formset.forms[0].formsets['songs'].forms)) @@ -493,7 +493,7 @@ def test_save_commit_false(self): beatles.save() first_song_id, second_song_id = first_song.id, second_song.id - AlbumsFormset = childformset_factory(Band, Album, form=ClusterForm, extra=3) + AlbumsFormset = childformset_factory(Band, Album, form=ClusterForm, formsets=['songs'], extra=3) albums_formset = AlbumsFormset({ 'form-TOTAL_FORMS': 1, @@ -555,7 +555,7 @@ def test_child_updates_without_ids(self): second_song = Song(name='Misery') album.songs.add(second_song) - AlbumsFormset = childformset_factory(Band, Album, form=ClusterForm, extra=3) + AlbumsFormset = childformset_factory(Band, Album, form=ClusterForm, formsets=['songs'], extra=3) albums_formset = AlbumsFormset({ 'form-TOTAL_FORMS': 1,