From 13efbb233a9aa2e3f13be863c6616ec0767a0d58 Mon Sep 17 00:00:00 2001 From: Matthias Kestenholz Date: Fri, 13 Apr 2018 17:08:30 +0200 Subject: [PATCH] Fixed #29322 -- Made admin check all ModelAdmin fieldsets for duplicates. --- django/contrib/admin/checks.py | 9 +++++---- tests/modeladmin/test_checks.py | 13 +++++++++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/django/contrib/admin/checks.py b/django/contrib/admin/checks.py index fc22a284382..e0f3a21550c 100644 --- a/django/contrib/admin/checks.py +++ b/django/contrib/admin/checks.py @@ -209,12 +209,13 @@ class BaseModelAdminChecks: elif not isinstance(obj.fieldsets, (list, tuple)): return must_be('a list or tuple', option='fieldsets', obj=obj, id='admin.E007') else: + seen_fields = [] return list(chain.from_iterable( - self._check_fieldsets_item(obj, obj.model, fieldset, 'fieldsets[%d]' % index) + self._check_fieldsets_item(obj, obj.model, fieldset, 'fieldsets[%d]' % index, seen_fields) for index, fieldset in enumerate(obj.fieldsets) )) - def _check_fieldsets_item(self, obj, model, fieldset, label): + def _check_fieldsets_item(self, obj, model, fieldset, label, seen_fields): """ Check an item of `fieldsets`, i.e. check that this is a pair of a set name and a dictionary containing "fields" key. """ @@ -235,8 +236,8 @@ class BaseModelAdminChecks: elif not isinstance(fieldset[1]['fields'], (list, tuple)): return must_be('a list or tuple', option="%s[1]['fields']" % label, obj=obj, id='admin.E008') - fields = flatten(fieldset[1]['fields']) - if len(fields) != len(set(fields)): + seen_fields.extend(flatten(fieldset[1]['fields'])) + if len(seen_fields) != len(set(seen_fields)): return [ checks.Error( "There are duplicate field(s) in '%s[1]'." % label, diff --git a/tests/modeladmin/test_checks.py b/tests/modeladmin/test_checks.py index f268fead156..fdbe2533964 100644 --- a/tests/modeladmin/test_checks.py +++ b/tests/modeladmin/test_checks.py @@ -166,6 +166,19 @@ class FieldsetsCheckTests(CheckTestCase): 'admin.E012' ) + def test_duplicate_fields_in_fieldsets(self): + class TestModelAdmin(ModelAdmin): + fieldsets = [ + (None, {'fields': ['name']}), + (None, {'fields': ['name']}), + ] + + self.assertIsInvalid( + TestModelAdmin, ValidationTestModel, + "There are duplicate field(s) in 'fieldsets[1][1]'.", + 'admin.E012' + ) + def test_fieldsets_with_custom_form_validation(self): class BandAdmin(ModelAdmin): fieldsets = (('Band', {'fields': ('name',)}),)