diff --git a/django/contrib/admin/checks.py b/django/contrib/admin/checks.py index c1a17af076da..94e700cf68c5 100644 --- a/django/contrib/admin/checks.py +++ b/django/contrib/admin/checks.py @@ -816,8 +816,7 @@ def check(self, admin_obj, **kwargs): *self._check_list_editable(admin_obj), *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), + *self._check_actions(admin_obj), ] def _check_save_as(self, obj): @@ -1195,13 +1194,12 @@ def _check_date_hierarchy(self, obj): else: return [] - def _check_action_permission_methods(self, obj): - """ - Actions with an allowed_permission attribute require the ModelAdmin to - implement a has__permission() method for each permission. - """ - actions = obj._get_base_actions() + def _check_actions(self, obj): errors = [] + actions = obj._get_base_actions() + + # Actions with an allowed_permission attribute require the ModelAdmin + # to implement a has__permission() method for each permission. for func, name, _ in actions: if not hasattr(func, "allowed_permissions"): continue @@ -1220,12 +1218,8 @@ def _check_action_permission_methods(self, obj): id="admin.E129", ) ) - return errors - - def _check_actions_uniqueness(self, obj): - """Check that every action has a unique __name__.""" - errors = [] - names = collections.Counter(name for _, name, _ in obj._get_base_actions()) + # Names need to be unique. + names = collections.Counter(name for _, name, _ in actions) for name, count in names.items(): if count > 1: errors.append( diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py index e93fdf40475d..47b4821fcc56 100644 --- a/django/contrib/admin/options.py +++ b/django/contrib/admin/options.py @@ -1033,7 +1033,10 @@ def action_checkbox(self, obj): @staticmethod def _get_action_description(func, name): - return getattr(func, "short_description", capfirst(name.replace("_", " "))) + try: + return func.short_description + except AttributeError: + return capfirst(name.replace("_", " ")) def _get_base_actions(self): """Return the list of actions, prior to any request-based filtering."""