Skip to content

Commit e233204

Browse files
committed
grouped admin actions
1 parent 4c7889c commit e233204

3 files changed

Lines changed: 69 additions & 20 deletions

File tree

.github/workflows/django-adminlink-ci.yml

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ jobs:
104104
python -m setuptools_scm
105105
python setup.py sdist bdist_wheel
106106
107-
test-publish:
107+
publish:
108108
runs-on: ubuntu-latest
109109
if: github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/')
110110
needs: [black, build, test, no-makemigrations, no-makemessages]
@@ -121,21 +121,3 @@ jobs:
121121
uses: pypa/gh-action-pypi-publish@release/v1
122122
with:
123123
verbose: true
124-
125-
publish:
126-
runs-on: ubuntu-latest
127-
needs: [test-publish]
128-
if: startsWith(github.ref, 'refs/tags/')
129-
steps:
130-
- name: checkout code
131-
uses: actions/checkout@v2.3.1
132-
- name: Set up Python
133-
uses: actions/setup-python@v4
134-
- run: |
135-
pip install 'setuptools>=38.6.0,<69.0' twine>=1.11.0 wheel>=0.31.0 setuptools_scm>=6.2
136-
python -m setuptools_scm
137-
python setup.py sdist bdist_wheel
138-
- name: Publish package
139-
uses: pypa/gh-action-pypi-publish@release/v1
140-
with:
141-
verbose: true

README.md

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,35 @@ from django_adminlink.admin import SingleItemActionMixin
8282
@admin.register(Movie)
8383
class MovieAdmin(SingleItemActionMixin, admin.ModelAdmin):
8484
action_buttons = ['delete_selected']
85-
```
85+
```
86+
87+
## Grouping actions
88+
89+
The list of actions is "flat". We can add item groups, just like in other Django `ChoiceField`s. For this we introduced the `GroupedActionAdminMixin`.
90+
91+
This mixin looks at the actions. We also defined a `@grouped_action` decorator, which does approximately the same as the `@admin.action` decorator, except with an extra parameter `action_group=…`.
92+
93+
We can register actions like:
94+
95+
```python3
96+
from django.contrib import admin
97+
from django_adminlink.admin import GroupedActionAdminMixin, grouped_action
98+
99+
@admin.register(Movie)
100+
class MovieAdmin(GroupedActionAdminMixin, admin.ModelAdmin):
101+
action_buttons = ['star', 'unstar', 'clear_comments']
102+
103+
@grouped_action(description='star item', action_group='stars')
104+
def star(self, request, queryset):
105+
#
106+
107+
@grouped_action(description='unstar item', action_group='stars')
108+
def unstar(self, request, queryset):
109+
#
110+
111+
@grouped_action(description='clear comments', action_group='comments')
112+
def clear_comments(self, request, queryset):
113+
#
114+
```
115+
116+
The order of the groups is determined by the order of the indivual actions: the first action for that group for each group determines how the groups are listed.

django_adminlink/admin.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
from collections import defaultdict
2+
13
from django.contrib import admin
4+
from django.contrib.admin.utils import model_format_dict
25
from django.core.exceptions import FieldDoesNotExist
36
from django.db import models
47
from django.forms import Media
@@ -127,3 +130,36 @@ def media(self):
127130

128131
class SingleItemActionAdmin(SingleItemActionMixin, admin.ModelAdmin):
129132
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

Comments
 (0)