Kaydet (Commit) f9ff1df1 authored tarafından Matthias Kestenholz's avatar Matthias Kestenholz Kaydeden (comit) Tim Graham

Fixed #29917 -- Stopped collecting ModelAdmin.actions from base ModelAdmins.

üst a375e911
...@@ -859,13 +859,8 @@ class ModelAdmin(BaseModelAdmin): ...@@ -859,13 +859,8 @@ class ModelAdmin(BaseModelAdmin):
for (name, func) in self.admin_site.actions: for (name, func) in self.admin_site.actions:
description = getattr(func, 'short_description', name.replace('_', ' ')) description = getattr(func, 'short_description', name.replace('_', ' '))
actions.append((func, name, description)) actions.append((func, name, description))
# Add actions from this ModelAdmin.
# Then gather them from the model admin and all parent classes, actions.extend(self.get_action(action) for action in self.actions or [])
# starting with self and working back up.
for klass in self.__class__.mro()[::-1]:
class_actions = getattr(klass, 'actions', []) or []
actions.extend(self.get_action(action) for action in class_actions)
# get_action might have returned None, so filter any of those out. # get_action might have returned None, so filter any of those out.
return filter(None, actions) return filter(None, actions)
......
...@@ -343,10 +343,8 @@ Conditionally enabling or disabling actions ...@@ -343,10 +343,8 @@ Conditionally enabling or disabling actions
This returns a dictionary of actions allowed. The keys are action names, and This returns a dictionary of actions allowed. The keys are action names, and
the values are ``(function, name, short_description)`` tuples. the values are ``(function, name, short_description)`` tuples.
Most of the time you'll use this method to conditionally remove actions from For example, if you only want users whose names begin with 'J' to be able
the list gathered by the superclass. For example, if I only wanted users to delete objects in bulk::
whose names begin with 'J' to be able to delete objects in bulk, I could do
the following::
class MyModelAdmin(admin.ModelAdmin): class MyModelAdmin(admin.ModelAdmin):
... ...
......
...@@ -293,6 +293,27 @@ Database backend API ...@@ -293,6 +293,27 @@ Database backend API
* Third party database backends must implement support for partial indexes or * Third party database backends must implement support for partial indexes or
set ``DatabaseFeatures.supports_partial_indexes`` to ``False``. set ``DatabaseFeatures.supports_partial_indexes`` to ``False``.
Admin actions are no longer collected from base ``ModelAdmin`` classes
----------------------------------------------------------------------
For example, in older versions of Django::
from django.contrib import admin
class BaseAdmin(admin.ModelAdmin):
actions = ['a']
class SubAdmin(BaseAdmin):
actions = ['b']
``SubAdmin`` will have actions ``'a'`` and ``'b'``.
Now ``actions`` follows standard Python inheritance. To get the same result as
before::
class SubAdmin(BaseAdmin):
actions = BaseAdmin.actions + ['b']
:mod:`django.contrib.gis` :mod:`django.contrib.gis`
------------------------- -------------------------
......
...@@ -55,3 +55,24 @@ class AdminActionsTests(TestCase): ...@@ -55,3 +55,24 @@ class AdminActionsTests(TestCase):
mock_request.user = user mock_request.user = user
actions = ma.get_actions(mock_request) actions = ma.get_actions(mock_request)
self.assertEqual(list(actions.keys()), expected) self.assertEqual(list(actions.keys()), expected)
def test_actions_inheritance(self):
class AdminBase(admin.ModelAdmin):
actions = ['custom_action']
def custom_action(modeladmin, request, queryset):
pass
class AdminA(AdminBase):
pass
class AdminB(AdminBase):
actions = None
ma1 = AdminA(Band, admin.AdminSite())
action_names = [name for _, name, _ in ma1._get_base_actions()]
self.assertEqual(action_names, ['delete_selected', 'custom_action'])
# `actions = None` removes actions from superclasses.
ma2 = AdminB(Band, admin.AdminSite())
action_names = [name for _, name, _ in ma2._get_base_actions()]
self.assertEqual(action_names, ['delete_selected'])
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment