diff --git a/AUTHORS b/AUTHORS index 76d9040fd5..75c894021f 100644 --- a/AUTHORS +++ b/AUTHORS @@ -686,6 +686,7 @@ answer newbie questions, and generally made Django that much better: Preston Holmes Preston Timmons Priyansh Saxena + Przemysław Buczkowski Przemysław Suliga Rachel Tobin Rachel Willmer diff --git a/django/contrib/admin/checks.py b/django/contrib/admin/checks.py index d129acb124..4007a781fb 100644 --- a/django/contrib/admin/checks.py +++ b/django/contrib/admin/checks.py @@ -606,6 +606,7 @@ class ModelAdminChecks(BaseModelAdminChecks): *self._check_search_fields(admin_obj), *self._check_date_hierarchy(admin_obj), *self._check_action_permission_methods(admin_obj), + *self._check_actions_uniqueness(admin_obj), ] def _check_save_as(self, obj): @@ -944,6 +945,18 @@ class ModelAdminChecks(BaseModelAdminChecks): ) return errors + def _check_actions_uniqueness(self, obj): + """Check that every action has a unique __name__.""" + names = [name for _, name, _ in obj._get_base_actions()] + if len(names) != len(set(names)): + return [checks.Error( + '__name__ attributes of actions defined in %s must be ' + 'unique.' % obj.__class__, + obj=obj.__class__, + id='admin.E130', + )] + return [] + class InlineModelAdminChecks(BaseModelAdminChecks): diff --git a/docs/ref/checks.txt b/docs/ref/checks.txt index 67813067f2..c8b13aa100 100644 --- a/docs/ref/checks.txt +++ b/docs/ref/checks.txt @@ -593,6 +593,8 @@ with the admin site: ``DateTimeField``. * **admin.E129**: ```` must define a ``has__permission()`` method for the ```` action. +* **admin.E130**: ``__name__`` attributes of actions defined in + ```` must be unique. ``InlineModelAdmin`` ~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/modeladmin/test_checks.py b/tests/modeladmin/test_checks.py index 6a10441471..89fde35d3c 100644 --- a/tests/modeladmin/test_checks.py +++ b/tests/modeladmin/test_checks.py @@ -1309,3 +1309,30 @@ class ActionsCheckTests(CheckTestCase): 'custom_permission_action action.', id='admin.E129', ) + + def test_actions_not_unique(self): + def action(modeladmin, request, queryset): + pass + + class BandAdmin(ModelAdmin): + actions = (action, action) + + self.assertIsInvalid( + BandAdmin, Band, + "__name__ attributes of actions defined in " + ".BandAdmin'> must be unique.", + id='admin.E130', + ) + + def test_actions_unique(self): + def action1(modeladmin, request, queryset): + pass + + def action2(modeladmin, request, queryset): + pass + + class BandAdmin(ModelAdmin): + actions = (action1, action2) + + self.assertIsValid(BandAdmin, Band)