|
| 1 | +from collections import defaultdict |
| 2 | + |
1 | 3 | from django.contrib import admin |
| 4 | +from django.contrib.admin.utils import model_format_dict |
2 | 5 | from django.core.exceptions import FieldDoesNotExist |
3 | 6 | from django.db import models |
4 | 7 | from django.forms import Media |
@@ -127,3 +130,36 @@ def media(self): |
127 | 130 |
|
128 | 131 | class SingleItemActionAdmin(SingleItemActionMixin, admin.ModelAdmin): |
129 | 132 | pass |
| 133 | + |
| 134 | + |
| 135 | +def grouped_action( |
| 136 | + function=None, *, permissions=None, description=None, action_group=None |
| 137 | +): |
| 138 | + if function is None: |
| 139 | + base_decorator = admin.action(permissions=permissions, description=description) |
| 140 | + |
| 141 | + def decorator(func): |
| 142 | + func = base_decorator(func) |
| 143 | + func.action_group = action_group |
| 144 | + return func |
| 145 | + |
| 146 | + return decorator |
| 147 | + else: |
| 148 | + function = admin.action(function) |
| 149 | + function.action_group = action_group |
| 150 | + return function |
| 151 | + |
| 152 | + |
| 153 | +class GroupedActionAdminMixin: |
| 154 | + def get_action_choices(self, request, default_choices=models.BLANK_CHOICE_DASH): |
| 155 | + grouped_items = defaultdict(list) |
| 156 | + grouped_items[None].extend(default_choices) |
| 157 | + for func, name, description in self.get_actions(request).values(): |
| 158 | + group = getattr(func, "action_group", None) |
| 159 | + choice = (name, description % model_format_dict(self.opts)) |
| 160 | + grouped_items[group].append(choice) |
| 161 | + return [(k, v) for k, v in grouped_items.items()] |
| 162 | + |
| 163 | + |
| 164 | +class GroupedActionAdmin(SingleItemActionMixin, admin.ModelAdmin): |
| 165 | + pass |
0 commit comments