1. from django.contrib import admin
    
  2. from django.contrib.auth.models import Permission, User
    
  3. from django.contrib.contenttypes.models import ContentType
    
  4. from django.test import TestCase
    
  5. 
    
  6. from .models import Band
    
  7. 
    
  8. 
    
  9. class AdminActionsTests(TestCase):
    
  10.     @classmethod
    
  11.     def setUpTestData(cls):
    
  12.         cls.superuser = User.objects.create_superuser(
    
  13.             username="super", password="secret", email="[email protected]"
    
  14.         )
    
  15.         content_type = ContentType.objects.get_for_model(Band)
    
  16.         Permission.objects.create(
    
  17.             name="custom", codename="custom_band", content_type=content_type
    
  18.         )
    
  19.         for user_type in ("view", "add", "change", "delete", "custom"):
    
  20.             username = "%suser" % user_type
    
  21.             user = User.objects.create_user(
    
  22.                 username=username, password="secret", is_staff=True
    
  23.             )
    
  24.             permission = Permission.objects.get(
    
  25.                 codename="%s_band" % user_type, content_type=content_type
    
  26.             )
    
  27.             user.user_permissions.add(permission)
    
  28.             setattr(cls, username, user)
    
  29. 
    
  30.     def test_get_actions_respects_permissions(self):
    
  31.         class MockRequest:
    
  32.             pass
    
  33. 
    
  34.         class BandAdmin(admin.ModelAdmin):
    
  35.             actions = ["custom_action"]
    
  36. 
    
  37.             @admin.action
    
  38.             def custom_action(modeladmin, request, queryset):
    
  39.                 pass
    
  40. 
    
  41.             def has_custom_permission(self, request):
    
  42.                 return request.user.has_perm("%s.custom_band" % self.opts.app_label)
    
  43. 
    
  44.         ma = BandAdmin(Band, admin.AdminSite())
    
  45.         mock_request = MockRequest()
    
  46.         mock_request.GET = {}
    
  47.         cases = [
    
  48.             (None, self.viewuser, ["custom_action"]),
    
  49.             ("view", self.superuser, ["delete_selected", "custom_action"]),
    
  50.             ("view", self.viewuser, ["custom_action"]),
    
  51.             ("add", self.adduser, ["custom_action"]),
    
  52.             ("change", self.changeuser, ["custom_action"]),
    
  53.             ("delete", self.deleteuser, ["delete_selected", "custom_action"]),
    
  54.             ("custom", self.customuser, ["custom_action"]),
    
  55.         ]
    
  56.         for permission, user, expected in cases:
    
  57.             with self.subTest(permission=permission, user=user):
    
  58.                 if permission is None:
    
  59.                     if hasattr(BandAdmin.custom_action, "allowed_permissions"):
    
  60.                         del BandAdmin.custom_action.allowed_permissions
    
  61.                 else:
    
  62.                     BandAdmin.custom_action.allowed_permissions = (permission,)
    
  63.                 mock_request.user = user
    
  64.                 actions = ma.get_actions(mock_request)
    
  65.                 self.assertEqual(list(actions.keys()), expected)
    
  66. 
    
  67.     def test_actions_inheritance(self):
    
  68.         class AdminBase(admin.ModelAdmin):
    
  69.             actions = ["custom_action"]
    
  70. 
    
  71.             @admin.action
    
  72.             def custom_action(modeladmin, request, queryset):
    
  73.                 pass
    
  74. 
    
  75.         class AdminA(AdminBase):
    
  76.             pass
    
  77. 
    
  78.         class AdminB(AdminBase):
    
  79.             actions = None
    
  80. 
    
  81.         ma1 = AdminA(Band, admin.AdminSite())
    
  82.         action_names = [name for _, name, _ in ma1._get_base_actions()]
    
  83.         self.assertEqual(action_names, ["delete_selected", "custom_action"])
    
  84.         # `actions = None` removes actions from superclasses.
    
  85.         ma2 = AdminB(Band, admin.AdminSite())
    
  86.         action_names = [name for _, name, _ in ma2._get_base_actions()]
    
  87.         self.assertEqual(action_names, ["delete_selected"])
    
  88. 
    
  89.     def test_global_actions_description(self):
    
  90.         @admin.action(description="Site-wide admin action 1.")
    
  91.         def global_action_1(modeladmin, request, queryset):
    
  92.             pass
    
  93. 
    
  94.         @admin.action
    
  95.         def global_action_2(modeladmin, request, queryset):
    
  96.             pass
    
  97. 
    
  98.         admin_site = admin.AdminSite()
    
  99.         admin_site.add_action(global_action_1)
    
  100.         admin_site.add_action(global_action_2)
    
  101. 
    
  102.         class BandAdmin(admin.ModelAdmin):
    
  103.             pass
    
  104. 
    
  105.         ma = BandAdmin(Band, admin_site)
    
  106.         self.assertEqual(
    
  107.             [description for _, _, description in ma._get_base_actions()],
    
  108.             [
    
  109.                 "Delete selected %(verbose_name_plural)s",
    
  110.                 "Site-wide admin action 1.",
    
  111.                 "Global action 2",
    
  112.             ],
    
  113.         )
    
  114. 
    
  115.     def test_actions_replace_global_action(self):
    
  116.         @admin.action(description="Site-wide admin action 1.")
    
  117.         def global_action_1(modeladmin, request, queryset):
    
  118.             pass
    
  119. 
    
  120.         @admin.action(description="Site-wide admin action 2.")
    
  121.         def global_action_2(modeladmin, request, queryset):
    
  122.             pass
    
  123. 
    
  124.         admin.site.add_action(global_action_1, name="custom_action_1")
    
  125.         admin.site.add_action(global_action_2, name="custom_action_2")
    
  126. 
    
  127.         @admin.action(description="Local admin action 1.")
    
  128.         def custom_action_1(modeladmin, request, queryset):
    
  129.             pass
    
  130. 
    
  131.         class BandAdmin(admin.ModelAdmin):
    
  132.             actions = [custom_action_1, "custom_action_2"]
    
  133. 
    
  134.             @admin.action(description="Local admin action 2.")
    
  135.             def custom_action_2(self, request, queryset):
    
  136.                 pass
    
  137. 
    
  138.         ma = BandAdmin(Band, admin.site)
    
  139.         self.assertEqual(ma.check(), [])
    
  140.         self.assertEqual(
    
  141.             [
    
  142.                 desc
    
  143.                 for _, name, desc in ma._get_base_actions()
    
  144.                 if name.startswith("custom_action")
    
  145.             ],
    
  146.             [
    
  147.                 "Local admin action 1.",
    
  148.                 "Local admin action 2.",
    
  149.             ],
    
  150.         )