django-subadmin-unfold 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. django_subadmin_unfold-1.0.0/LICENSE +21 -0
  2. django_subadmin_unfold-1.0.0/MANIFEST.in +2 -0
  3. django_subadmin_unfold-1.0.0/PKG-INFO +197 -0
  4. django_subadmin_unfold-1.0.0/README.md +178 -0
  5. django_subadmin_unfold-1.0.0/django_subadmin_unfold.egg-info/PKG-INFO +197 -0
  6. django_subadmin_unfold-1.0.0/django_subadmin_unfold.egg-info/SOURCES.txt +27 -0
  7. django_subadmin_unfold-1.0.0/django_subadmin_unfold.egg-info/dependency_links.txt +1 -0
  8. django_subadmin_unfold-1.0.0/django_subadmin_unfold.egg-info/requires.txt +3 -0
  9. django_subadmin_unfold-1.0.0/django_subadmin_unfold.egg-info/top_level.txt +1 -0
  10. django_subadmin_unfold-1.0.0/pyproject.toml +31 -0
  11. django_subadmin_unfold-1.0.0/setup.cfg +4 -0
  12. django_subadmin_unfold-1.0.0/subadmin_unfold/__init__.py +0 -0
  13. django_subadmin_unfold-1.0.0/subadmin_unfold/admin.py +182 -0
  14. django_subadmin_unfold-1.0.0/subadmin_unfold/apps.py +5 -0
  15. django_subadmin_unfold-1.0.0/subadmin_unfold/datasets.py +35 -0
  16. django_subadmin_unfold-1.0.0/subadmin_unfold/templates/subadmin_unfold/change_form.html +28 -0
  17. django_subadmin_unfold-1.0.0/subadmin_unfold/templates/subadmin_unfold/change_list.html +14 -0
  18. django_subadmin_unfold-1.0.0/subadmin_unfold/templates/subadmin_unfold/delete_confirmation.html +2 -0
  19. django_subadmin_unfold-1.0.0/subadmin_unfold/templates/subadmin_unfold/delete_selected_confirmation.html +2 -0
  20. django_subadmin_unfold-1.0.0/subadmin_unfold/templates/subadmin_unfold/header.html +52 -0
  21. django_subadmin_unfold-1.0.0/subadmin_unfold/templates/subadmin_unfold/object_history.html +2 -0
  22. django_subadmin_unfold-1.0.0/subadmin_unfold/templates/subadmin_unfold/parent_change_form.html +9 -0
  23. django_subadmin_unfold-1.0.0/subadmin_unfold/templates/subadmin_unfold/subadmin_links.html +3 -0
  24. django_subadmin_unfold-1.0.0/subadmin_unfold/templates/subadmin_unfold/submit_line.html +35 -0
  25. django_subadmin_unfold-1.0.0/subadmin_unfold/templates/unfold/helpers/actions_row.html +56 -0
  26. django_subadmin_unfold-1.0.0/subadmin_unfold/templatetags/__init__.py +0 -0
  27. django_subadmin_unfold-1.0.0/subadmin_unfold/templatetags/subadmin_unfold.py +70 -0
  28. django_subadmin_unfold-1.0.0/tests/test_datasets.py +156 -0
  29. django_subadmin_unfold-1.0.0/tests/test_pages.py +334 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mitja Pagon
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,2 @@
1
+ include LICENSE
2
+ recursive-include subadmin_unfold/templates *.html
@@ -0,0 +1,197 @@
1
+ Metadata-Version: 2.4
2
+ Name: django-subadmin-unfold
3
+ Version: 1.0.0
4
+ Summary: Django Unfold integration for django-subadmin
5
+ License-Expression: MIT
6
+ Classifier: Framework :: Django :: 5.2
7
+ Classifier: Framework :: Django :: 6.0
8
+ Classifier: Framework :: Django :: 6.1
9
+ Classifier: Programming Language :: Python :: 3.12
10
+ Classifier: Programming Language :: Python :: 3.13
11
+ Classifier: Programming Language :: Python :: 3.14
12
+ Requires-Python: >=3.12
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+ Requires-Dist: Django>=5.2
16
+ Requires-Dist: django-subadmin>=5.2
17
+ Requires-Dist: django-unfold>=0.102
18
+ Dynamic: license-file
19
+
20
+ # django-subadmin-unfold
21
+
22
+ `django-subadmin-unfold` makes
23
+ [django-subadmin](https://github.com/inueni/django-subadmin)'s nested model
24
+ admins feel at home in [Django Unfold](https://unfoldadmin.com/), from
25
+ navigation and breadcrumbs to custom actions.
26
+
27
+ ## Installation
28
+
29
+ ```console
30
+ pip install django-subadmin-unfold
31
+ ```
32
+
33
+ The package requires Python 3.12+, Django 5.2+, django-subadmin 5.2+, and
34
+ django-unfold 0.102+. It has been tested with Django 5.2, 6.0, and 6.1. Add
35
+ the apps in this order so the adapter's templates are used:
36
+
37
+ ```python
38
+ # settings.py
39
+ INSTALLED_APPS = [
40
+ "subadmin_unfold",
41
+ "unfold",
42
+ "subadmin",
43
+ "django.contrib.admin",
44
+ # Django's other contrib apps and your own apps...
45
+ ]
46
+ ```
47
+
48
+ ## Using it
49
+
50
+ Start with the [django-subadmin example](https://github.com/inueni/django-subadmin#example).
51
+ The model relationships are the same. Use `UnfoldSubAdmin` for nested admins
52
+ and `UnfoldRootSubAdmin` for the registered parent admin:
53
+
54
+ ```python
55
+ from django.contrib import admin
56
+ from subadmin_unfold.admin import UnfoldRootSubAdmin, UnfoldSubAdmin
57
+
58
+ from .models import Child, Parent
59
+
60
+
61
+ class ChildAdmin(UnfoldSubAdmin):
62
+ model = Child
63
+
64
+
65
+ @admin.register(Parent)
66
+ class ParentAdmin(UnfoldRootSubAdmin):
67
+ subadmins = (ChildAdmin,)
68
+ ```
69
+
70
+ The nested list and change pages use Unfold's templates and breadcrumbs.
71
+
72
+ ![Child list nested under Example parent](https://raw.githubusercontent.com/inueni/django-subadmin-unfold/1.0.0/docs/images/subadmin-children-list.png)
73
+
74
+ ## Grouping subadmin links
75
+
76
+ Django admin has no subadmin links, and django-subadmin displays each link
77
+ separately. This adapter lets you group links into dropdowns, following
78
+ Unfold's dropdown actions pattern. Here **Children** stays as a direct link,
79
+ while **Notes** and **Documents** sit under **Related**:
80
+
81
+ ```python
82
+ subadmins = (
83
+ ChildAdmin,
84
+ {
85
+ "title": "Related",
86
+ "icon": "folder",
87
+ "items": (NoteAdmin, DocumentAdmin),
88
+ },
89
+ )
90
+ ```
91
+
92
+ ![Parent admin with a direct Children link and an open Related dropdown](https://raw.githubusercontent.com/inueni/django-subadmin-unfold/1.0.0/docs/images/subadmin-parent-grouped-links.png)
93
+
94
+ `NoteAdmin` and `DocumentAdmin` are defined like `ChildAdmin`. Groups work on
95
+ root and nested admins. A group with no permitted links is hidden; one
96
+ permitted link still appears in a dropdown.
97
+
98
+ ## Icons
99
+
100
+ Set `subadmin_icon` on a nested admin to give its link a
101
+ [Material Symbols](https://fonts.google.com/icons) icon:
102
+
103
+ ```python
104
+ class ChildAdmin(UnfoldSubAdmin):
105
+ model = Child
106
+ subadmin_icon = "groups"
107
+ ```
108
+
109
+ The default link icon is `view_list`. To change it for all subadmins, set
110
+ `SUBADMIN_UNFOLD_DEFAULT_ICON` in your Django settings:
111
+
112
+ ```python
113
+ SUBADMIN_UNFOLD_DEFAULT_ICON = "list_alt"
114
+ ```
115
+
116
+ A class's `subadmin_icon` takes precedence over this setting. Both work for
117
+ direct links and links inside groups. Set a dropdown's icon with the group's
118
+ `icon` key, as above.
119
+
120
+ ## Datasets
121
+
122
+ [Unfold datasets](https://unfoldadmin.com/docs/configuration/datasets/) display
123
+ a changelist inside a change form. Regular `BaseDataset` works on subadmin
124
+ pages. Use `SubAdminDataset` when the dataset's rows should link to a direct
125
+ child subadmin's change pages.
126
+
127
+ The following setup shows Children on a Parent change form. It replaces the
128
+ short `admin.py` example above. `ChildAdmin` provides the full nested pages,
129
+ `ChildDatasetAdmin` configures and filters the embedded table, and
130
+ `ChildDataset` points table rows to those nested pages:
131
+
132
+ ```python
133
+ from django.contrib import admin
134
+ from django.contrib.admin.utils import unquote
135
+ from subadmin_unfold.admin import UnfoldRootSubAdmin, UnfoldSubAdmin
136
+ from subadmin_unfold.datasets import SubAdminDataset
137
+ from unfold.admin import ModelAdmin
138
+
139
+ from .models import Child, Parent
140
+
141
+
142
+ class ChildAdmin(UnfoldSubAdmin):
143
+ model = Child
144
+
145
+
146
+ class ChildDatasetAdmin(ModelAdmin):
147
+ list_display = ("name",)
148
+
149
+ def get_queryset(self, request):
150
+ queryset = super().get_queryset(request)
151
+ parent_id = (self.extra_context or {}).get("object")
152
+ if not parent_id or not self.has_view_or_change_permission(request):
153
+ return queryset.none()
154
+ return queryset.filter(parent_id=unquote(parent_id))
155
+
156
+
157
+ class ChildDataset(SubAdminDataset):
158
+ model = Child
159
+ model_admin = ChildDatasetAdmin
160
+
161
+
162
+ @admin.register(Parent)
163
+ class ParentAdmin(UnfoldRootSubAdmin):
164
+ subadmins = (ChildAdmin,)
165
+ change_form_datasets = (ChildDataset,)
166
+ ```
167
+
168
+ `ChildDatasetAdmin` is a separate, unregistered admin used by Unfold to render
169
+ the table. Its queryset must enforce parent scope and any child visibility
170
+ rules. `SubAdminDataset` only changes row links; it does not create detail pages
171
+ or inherit settings from `ChildAdmin`.
172
+
173
+ ## Unfold actions
174
+
175
+ Define [Unfold actions](https://unfoldadmin.com/docs/actions/introduction/) on
176
+ `UnfoldSubAdmin` as you would on an Unfold `ModelAdmin`. List, detail, row, and
177
+ submit-line actions are supported. For example, a list action can use
178
+ `request.subadmin` to access the current parent:
179
+
180
+ ```python
181
+ from django.http import HttpResponse
182
+ from unfold.decorators import action
183
+
184
+
185
+ class ChildAdmin(UnfoldSubAdmin):
186
+ model = Child
187
+ actions_list = ("show_parent",)
188
+
189
+ @action(description="Show parent", icon="account_tree")
190
+ def show_parent(self, request):
191
+ return HttpResponse(request.subadmin.parent_instance.name)
192
+ ```
193
+
194
+ The adapter includes the parent IDs in nested action URLs. Nested admins can
195
+ also define `get_custom_urls()`; those views receive `model_admin` and
196
+ `request.subadmin`. Reverse a nested custom URL with
197
+ `model_admin.reverse_url(name, *parent_ids, *custom_args)`.
@@ -0,0 +1,178 @@
1
+ # django-subadmin-unfold
2
+
3
+ `django-subadmin-unfold` makes
4
+ [django-subadmin](https://github.com/inueni/django-subadmin)'s nested model
5
+ admins feel at home in [Django Unfold](https://unfoldadmin.com/), from
6
+ navigation and breadcrumbs to custom actions.
7
+
8
+ ## Installation
9
+
10
+ ```console
11
+ pip install django-subadmin-unfold
12
+ ```
13
+
14
+ The package requires Python 3.12+, Django 5.2+, django-subadmin 5.2+, and
15
+ django-unfold 0.102+. It has been tested with Django 5.2, 6.0, and 6.1. Add
16
+ the apps in this order so the adapter's templates are used:
17
+
18
+ ```python
19
+ # settings.py
20
+ INSTALLED_APPS = [
21
+ "subadmin_unfold",
22
+ "unfold",
23
+ "subadmin",
24
+ "django.contrib.admin",
25
+ # Django's other contrib apps and your own apps...
26
+ ]
27
+ ```
28
+
29
+ ## Using it
30
+
31
+ Start with the [django-subadmin example](https://github.com/inueni/django-subadmin#example).
32
+ The model relationships are the same. Use `UnfoldSubAdmin` for nested admins
33
+ and `UnfoldRootSubAdmin` for the registered parent admin:
34
+
35
+ ```python
36
+ from django.contrib import admin
37
+ from subadmin_unfold.admin import UnfoldRootSubAdmin, UnfoldSubAdmin
38
+
39
+ from .models import Child, Parent
40
+
41
+
42
+ class ChildAdmin(UnfoldSubAdmin):
43
+ model = Child
44
+
45
+
46
+ @admin.register(Parent)
47
+ class ParentAdmin(UnfoldRootSubAdmin):
48
+ subadmins = (ChildAdmin,)
49
+ ```
50
+
51
+ The nested list and change pages use Unfold's templates and breadcrumbs.
52
+
53
+ ![Child list nested under Example parent](https://raw.githubusercontent.com/inueni/django-subadmin-unfold/1.0.0/docs/images/subadmin-children-list.png)
54
+
55
+ ## Grouping subadmin links
56
+
57
+ Django admin has no subadmin links, and django-subadmin displays each link
58
+ separately. This adapter lets you group links into dropdowns, following
59
+ Unfold's dropdown actions pattern. Here **Children** stays as a direct link,
60
+ while **Notes** and **Documents** sit under **Related**:
61
+
62
+ ```python
63
+ subadmins = (
64
+ ChildAdmin,
65
+ {
66
+ "title": "Related",
67
+ "icon": "folder",
68
+ "items": (NoteAdmin, DocumentAdmin),
69
+ },
70
+ )
71
+ ```
72
+
73
+ ![Parent admin with a direct Children link and an open Related dropdown](https://raw.githubusercontent.com/inueni/django-subadmin-unfold/1.0.0/docs/images/subadmin-parent-grouped-links.png)
74
+
75
+ `NoteAdmin` and `DocumentAdmin` are defined like `ChildAdmin`. Groups work on
76
+ root and nested admins. A group with no permitted links is hidden; one
77
+ permitted link still appears in a dropdown.
78
+
79
+ ## Icons
80
+
81
+ Set `subadmin_icon` on a nested admin to give its link a
82
+ [Material Symbols](https://fonts.google.com/icons) icon:
83
+
84
+ ```python
85
+ class ChildAdmin(UnfoldSubAdmin):
86
+ model = Child
87
+ subadmin_icon = "groups"
88
+ ```
89
+
90
+ The default link icon is `view_list`. To change it for all subadmins, set
91
+ `SUBADMIN_UNFOLD_DEFAULT_ICON` in your Django settings:
92
+
93
+ ```python
94
+ SUBADMIN_UNFOLD_DEFAULT_ICON = "list_alt"
95
+ ```
96
+
97
+ A class's `subadmin_icon` takes precedence over this setting. Both work for
98
+ direct links and links inside groups. Set a dropdown's icon with the group's
99
+ `icon` key, as above.
100
+
101
+ ## Datasets
102
+
103
+ [Unfold datasets](https://unfoldadmin.com/docs/configuration/datasets/) display
104
+ a changelist inside a change form. Regular `BaseDataset` works on subadmin
105
+ pages. Use `SubAdminDataset` when the dataset's rows should link to a direct
106
+ child subadmin's change pages.
107
+
108
+ The following setup shows Children on a Parent change form. It replaces the
109
+ short `admin.py` example above. `ChildAdmin` provides the full nested pages,
110
+ `ChildDatasetAdmin` configures and filters the embedded table, and
111
+ `ChildDataset` points table rows to those nested pages:
112
+
113
+ ```python
114
+ from django.contrib import admin
115
+ from django.contrib.admin.utils import unquote
116
+ from subadmin_unfold.admin import UnfoldRootSubAdmin, UnfoldSubAdmin
117
+ from subadmin_unfold.datasets import SubAdminDataset
118
+ from unfold.admin import ModelAdmin
119
+
120
+ from .models import Child, Parent
121
+
122
+
123
+ class ChildAdmin(UnfoldSubAdmin):
124
+ model = Child
125
+
126
+
127
+ class ChildDatasetAdmin(ModelAdmin):
128
+ list_display = ("name",)
129
+
130
+ def get_queryset(self, request):
131
+ queryset = super().get_queryset(request)
132
+ parent_id = (self.extra_context or {}).get("object")
133
+ if not parent_id or not self.has_view_or_change_permission(request):
134
+ return queryset.none()
135
+ return queryset.filter(parent_id=unquote(parent_id))
136
+
137
+
138
+ class ChildDataset(SubAdminDataset):
139
+ model = Child
140
+ model_admin = ChildDatasetAdmin
141
+
142
+
143
+ @admin.register(Parent)
144
+ class ParentAdmin(UnfoldRootSubAdmin):
145
+ subadmins = (ChildAdmin,)
146
+ change_form_datasets = (ChildDataset,)
147
+ ```
148
+
149
+ `ChildDatasetAdmin` is a separate, unregistered admin used by Unfold to render
150
+ the table. Its queryset must enforce parent scope and any child visibility
151
+ rules. `SubAdminDataset` only changes row links; it does not create detail pages
152
+ or inherit settings from `ChildAdmin`.
153
+
154
+ ## Unfold actions
155
+
156
+ Define [Unfold actions](https://unfoldadmin.com/docs/actions/introduction/) on
157
+ `UnfoldSubAdmin` as you would on an Unfold `ModelAdmin`. List, detail, row, and
158
+ submit-line actions are supported. For example, a list action can use
159
+ `request.subadmin` to access the current parent:
160
+
161
+ ```python
162
+ from django.http import HttpResponse
163
+ from unfold.decorators import action
164
+
165
+
166
+ class ChildAdmin(UnfoldSubAdmin):
167
+ model = Child
168
+ actions_list = ("show_parent",)
169
+
170
+ @action(description="Show parent", icon="account_tree")
171
+ def show_parent(self, request):
172
+ return HttpResponse(request.subadmin.parent_instance.name)
173
+ ```
174
+
175
+ The adapter includes the parent IDs in nested action URLs. Nested admins can
176
+ also define `get_custom_urls()`; those views receive `model_admin` and
177
+ `request.subadmin`. Reverse a nested custom URL with
178
+ `model_admin.reverse_url(name, *parent_ids, *custom_args)`.
@@ -0,0 +1,197 @@
1
+ Metadata-Version: 2.4
2
+ Name: django-subadmin-unfold
3
+ Version: 1.0.0
4
+ Summary: Django Unfold integration for django-subadmin
5
+ License-Expression: MIT
6
+ Classifier: Framework :: Django :: 5.2
7
+ Classifier: Framework :: Django :: 6.0
8
+ Classifier: Framework :: Django :: 6.1
9
+ Classifier: Programming Language :: Python :: 3.12
10
+ Classifier: Programming Language :: Python :: 3.13
11
+ Classifier: Programming Language :: Python :: 3.14
12
+ Requires-Python: >=3.12
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+ Requires-Dist: Django>=5.2
16
+ Requires-Dist: django-subadmin>=5.2
17
+ Requires-Dist: django-unfold>=0.102
18
+ Dynamic: license-file
19
+
20
+ # django-subadmin-unfold
21
+
22
+ `django-subadmin-unfold` makes
23
+ [django-subadmin](https://github.com/inueni/django-subadmin)'s nested model
24
+ admins feel at home in [Django Unfold](https://unfoldadmin.com/), from
25
+ navigation and breadcrumbs to custom actions.
26
+
27
+ ## Installation
28
+
29
+ ```console
30
+ pip install django-subadmin-unfold
31
+ ```
32
+
33
+ The package requires Python 3.12+, Django 5.2+, django-subadmin 5.2+, and
34
+ django-unfold 0.102+. It has been tested with Django 5.2, 6.0, and 6.1. Add
35
+ the apps in this order so the adapter's templates are used:
36
+
37
+ ```python
38
+ # settings.py
39
+ INSTALLED_APPS = [
40
+ "subadmin_unfold",
41
+ "unfold",
42
+ "subadmin",
43
+ "django.contrib.admin",
44
+ # Django's other contrib apps and your own apps...
45
+ ]
46
+ ```
47
+
48
+ ## Using it
49
+
50
+ Start with the [django-subadmin example](https://github.com/inueni/django-subadmin#example).
51
+ The model relationships are the same. Use `UnfoldSubAdmin` for nested admins
52
+ and `UnfoldRootSubAdmin` for the registered parent admin:
53
+
54
+ ```python
55
+ from django.contrib import admin
56
+ from subadmin_unfold.admin import UnfoldRootSubAdmin, UnfoldSubAdmin
57
+
58
+ from .models import Child, Parent
59
+
60
+
61
+ class ChildAdmin(UnfoldSubAdmin):
62
+ model = Child
63
+
64
+
65
+ @admin.register(Parent)
66
+ class ParentAdmin(UnfoldRootSubAdmin):
67
+ subadmins = (ChildAdmin,)
68
+ ```
69
+
70
+ The nested list and change pages use Unfold's templates and breadcrumbs.
71
+
72
+ ![Child list nested under Example parent](https://raw.githubusercontent.com/inueni/django-subadmin-unfold/1.0.0/docs/images/subadmin-children-list.png)
73
+
74
+ ## Grouping subadmin links
75
+
76
+ Django admin has no subadmin links, and django-subadmin displays each link
77
+ separately. This adapter lets you group links into dropdowns, following
78
+ Unfold's dropdown actions pattern. Here **Children** stays as a direct link,
79
+ while **Notes** and **Documents** sit under **Related**:
80
+
81
+ ```python
82
+ subadmins = (
83
+ ChildAdmin,
84
+ {
85
+ "title": "Related",
86
+ "icon": "folder",
87
+ "items": (NoteAdmin, DocumentAdmin),
88
+ },
89
+ )
90
+ ```
91
+
92
+ ![Parent admin with a direct Children link and an open Related dropdown](https://raw.githubusercontent.com/inueni/django-subadmin-unfold/1.0.0/docs/images/subadmin-parent-grouped-links.png)
93
+
94
+ `NoteAdmin` and `DocumentAdmin` are defined like `ChildAdmin`. Groups work on
95
+ root and nested admins. A group with no permitted links is hidden; one
96
+ permitted link still appears in a dropdown.
97
+
98
+ ## Icons
99
+
100
+ Set `subadmin_icon` on a nested admin to give its link a
101
+ [Material Symbols](https://fonts.google.com/icons) icon:
102
+
103
+ ```python
104
+ class ChildAdmin(UnfoldSubAdmin):
105
+ model = Child
106
+ subadmin_icon = "groups"
107
+ ```
108
+
109
+ The default link icon is `view_list`. To change it for all subadmins, set
110
+ `SUBADMIN_UNFOLD_DEFAULT_ICON` in your Django settings:
111
+
112
+ ```python
113
+ SUBADMIN_UNFOLD_DEFAULT_ICON = "list_alt"
114
+ ```
115
+
116
+ A class's `subadmin_icon` takes precedence over this setting. Both work for
117
+ direct links and links inside groups. Set a dropdown's icon with the group's
118
+ `icon` key, as above.
119
+
120
+ ## Datasets
121
+
122
+ [Unfold datasets](https://unfoldadmin.com/docs/configuration/datasets/) display
123
+ a changelist inside a change form. Regular `BaseDataset` works on subadmin
124
+ pages. Use `SubAdminDataset` when the dataset's rows should link to a direct
125
+ child subadmin's change pages.
126
+
127
+ The following setup shows Children on a Parent change form. It replaces the
128
+ short `admin.py` example above. `ChildAdmin` provides the full nested pages,
129
+ `ChildDatasetAdmin` configures and filters the embedded table, and
130
+ `ChildDataset` points table rows to those nested pages:
131
+
132
+ ```python
133
+ from django.contrib import admin
134
+ from django.contrib.admin.utils import unquote
135
+ from subadmin_unfold.admin import UnfoldRootSubAdmin, UnfoldSubAdmin
136
+ from subadmin_unfold.datasets import SubAdminDataset
137
+ from unfold.admin import ModelAdmin
138
+
139
+ from .models import Child, Parent
140
+
141
+
142
+ class ChildAdmin(UnfoldSubAdmin):
143
+ model = Child
144
+
145
+
146
+ class ChildDatasetAdmin(ModelAdmin):
147
+ list_display = ("name",)
148
+
149
+ def get_queryset(self, request):
150
+ queryset = super().get_queryset(request)
151
+ parent_id = (self.extra_context or {}).get("object")
152
+ if not parent_id or not self.has_view_or_change_permission(request):
153
+ return queryset.none()
154
+ return queryset.filter(parent_id=unquote(parent_id))
155
+
156
+
157
+ class ChildDataset(SubAdminDataset):
158
+ model = Child
159
+ model_admin = ChildDatasetAdmin
160
+
161
+
162
+ @admin.register(Parent)
163
+ class ParentAdmin(UnfoldRootSubAdmin):
164
+ subadmins = (ChildAdmin,)
165
+ change_form_datasets = (ChildDataset,)
166
+ ```
167
+
168
+ `ChildDatasetAdmin` is a separate, unregistered admin used by Unfold to render
169
+ the table. Its queryset must enforce parent scope and any child visibility
170
+ rules. `SubAdminDataset` only changes row links; it does not create detail pages
171
+ or inherit settings from `ChildAdmin`.
172
+
173
+ ## Unfold actions
174
+
175
+ Define [Unfold actions](https://unfoldadmin.com/docs/actions/introduction/) on
176
+ `UnfoldSubAdmin` as you would on an Unfold `ModelAdmin`. List, detail, row, and
177
+ submit-line actions are supported. For example, a list action can use
178
+ `request.subadmin` to access the current parent:
179
+
180
+ ```python
181
+ from django.http import HttpResponse
182
+ from unfold.decorators import action
183
+
184
+
185
+ class ChildAdmin(UnfoldSubAdmin):
186
+ model = Child
187
+ actions_list = ("show_parent",)
188
+
189
+ @action(description="Show parent", icon="account_tree")
190
+ def show_parent(self, request):
191
+ return HttpResponse(request.subadmin.parent_instance.name)
192
+ ```
193
+
194
+ The adapter includes the parent IDs in nested action URLs. Nested admins can
195
+ also define `get_custom_urls()`; those views receive `model_admin` and
196
+ `request.subadmin`. Reverse a nested custom URL with
197
+ `model_admin.reverse_url(name, *parent_ids, *custom_args)`.
@@ -0,0 +1,27 @@
1
+ LICENSE
2
+ MANIFEST.in
3
+ README.md
4
+ pyproject.toml
5
+ django_subadmin_unfold.egg-info/PKG-INFO
6
+ django_subadmin_unfold.egg-info/SOURCES.txt
7
+ django_subadmin_unfold.egg-info/dependency_links.txt
8
+ django_subadmin_unfold.egg-info/requires.txt
9
+ django_subadmin_unfold.egg-info/top_level.txt
10
+ subadmin_unfold/__init__.py
11
+ subadmin_unfold/admin.py
12
+ subadmin_unfold/apps.py
13
+ subadmin_unfold/datasets.py
14
+ subadmin_unfold/templates/subadmin_unfold/change_form.html
15
+ subadmin_unfold/templates/subadmin_unfold/change_list.html
16
+ subadmin_unfold/templates/subadmin_unfold/delete_confirmation.html
17
+ subadmin_unfold/templates/subadmin_unfold/delete_selected_confirmation.html
18
+ subadmin_unfold/templates/subadmin_unfold/header.html
19
+ subadmin_unfold/templates/subadmin_unfold/object_history.html
20
+ subadmin_unfold/templates/subadmin_unfold/parent_change_form.html
21
+ subadmin_unfold/templates/subadmin_unfold/subadmin_links.html
22
+ subadmin_unfold/templates/subadmin_unfold/submit_line.html
23
+ subadmin_unfold/templates/unfold/helpers/actions_row.html
24
+ subadmin_unfold/templatetags/__init__.py
25
+ subadmin_unfold/templatetags/subadmin_unfold.py
26
+ tests/test_datasets.py
27
+ tests/test_pages.py
@@ -0,0 +1,3 @@
1
+ Django>=5.2
2
+ django-subadmin>=5.2
3
+ django-unfold>=0.102
@@ -0,0 +1,31 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "django-subadmin-unfold"
7
+ version = "1.0.0"
8
+ description = "Django Unfold integration for django-subadmin"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ license-files = ["LICENSE"]
12
+ requires-python = ">=3.12"
13
+ dependencies = [
14
+ "Django>=5.2",
15
+ "django-subadmin>=5.2",
16
+ "django-unfold>=0.102",
17
+ ]
18
+ classifiers = [
19
+ "Framework :: Django :: 5.2",
20
+ "Framework :: Django :: 6.0",
21
+ "Framework :: Django :: 6.1",
22
+ "Programming Language :: Python :: 3.12",
23
+ "Programming Language :: Python :: 3.13",
24
+ "Programming Language :: Python :: 3.14",
25
+ ]
26
+
27
+ [tool.setuptools.package-data]
28
+ subadmin_unfold = ["templates/**/*.html"]
29
+
30
+ [tool.ruff]
31
+ line-length = 88
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+