django-unfold 0.49.1__py3-none-any.whl → 0.51.0__py3-none-any.whl
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.
- django_unfold-0.51.0.dist-info/METADATA +81 -0
- {django_unfold-0.49.1.dist-info → django_unfold-0.51.0.dist-info}/RECORD +34 -30
- {django_unfold-0.49.1.dist-info → django_unfold-0.51.0.dist-info}/WHEEL +1 -1
- unfold/admin.py +4 -0
- unfold/contrib/filters/admin/dropdown_filters.py +1 -0
- unfold/contrib/filters/admin/mixins.py +10 -4
- unfold/contrib/filters/forms.py +2 -2
- unfold/dataclasses.py +3 -0
- unfold/decorators.py +8 -0
- unfold/enums.py +10 -0
- unfold/mixins/action_model_admin.py +4 -0
- unfold/sections.py +82 -0
- unfold/settings.py +1 -0
- unfold/sites.py +3 -0
- unfold/static/admin/js/inlines.js +18 -5
- unfold/static/unfold/css/styles.css +1 -1
- unfold/static/unfold/js/select2.init.js +29 -0
- unfold/styles.css +1 -1
- unfold/templates/admin/change_list.html +16 -16
- unfold/templates/admin/change_list_results.html +38 -40
- unfold/templates/admin/filter.html +2 -2
- unfold/templates/unfold/components/card.html +1 -1
- unfold/templates/unfold/components/table.html +42 -26
- unfold/templates/unfold/helpers/change_list_filter_actions.html +1 -1
- unfold/templates/unfold/helpers/empty_results.html +35 -0
- unfold/templates/unfold/helpers/tab_action.html +24 -19
- unfold/templates/unfold/helpers/tab_actions.html +19 -0
- unfold/templates/unfold/helpers/tab_items.html +47 -0
- unfold/templates/unfold/helpers/tab_list.html +3 -66
- unfold/templates/unfold/layouts/skeleton.html +1 -2
- unfold/templatetags/unfold.py +81 -2
- unfold/templatetags/unfold_list.py +10 -10
- unfold/views.py +14 -1
- django_unfold-0.49.1.dist-info/METADATA +0 -75
- unfold/contrib/filters/admin.py +0 -619
- {django_unfold-0.49.1.dist-info → django_unfold-0.51.0.dist-info}/LICENSE.md +0 -0
unfold/templatetags/unfold.py
CHANGED
@@ -4,6 +4,7 @@ from typing import Any, Optional, Union
|
|
4
4
|
from django import template
|
5
5
|
from django.contrib.admin.helpers import AdminForm, Fieldset
|
6
6
|
from django.contrib.admin.views.main import ChangeList
|
7
|
+
from django.db.models import Model
|
7
8
|
from django.db.models.options import Options
|
8
9
|
from django.forms import Field
|
9
10
|
from django.http import HttpRequest
|
@@ -13,6 +14,8 @@ from django.template.loader import render_to_string
|
|
13
14
|
from django.utils.safestring import SafeText
|
14
15
|
|
15
16
|
from unfold.components import ComponentRegistry
|
17
|
+
from unfold.dataclasses import UnfoldAction
|
18
|
+
from unfold.enums import ActionVariant
|
16
19
|
|
17
20
|
register = Library()
|
18
21
|
|
@@ -83,6 +86,11 @@ def tab_list(context: RequestContext, page: str, opts: Optional[Options] = None)
|
|
83
86
|
)
|
84
87
|
|
85
88
|
|
89
|
+
@register.simple_tag(name="render_section", takes_context=True)
|
90
|
+
def render_section(context: Context, section_class, instance: Model) -> str:
|
91
|
+
return section_class(context.request, instance).render()
|
92
|
+
|
93
|
+
|
86
94
|
@register.simple_tag(name="has_nav_item_active")
|
87
95
|
def has_nav_item_active(items: list) -> bool:
|
88
96
|
for item in items:
|
@@ -212,14 +220,17 @@ class RenderComponentNode(template.Node):
|
|
212
220
|
|
213
221
|
if "component_class" in values:
|
214
222
|
values = ComponentRegistry.create_instance(
|
215
|
-
values["component_class"],
|
223
|
+
values["component_class"],
|
224
|
+
request=context.request if hasattr(context, "request") else None,
|
216
225
|
).get_context_data(**values)
|
217
226
|
|
218
227
|
if self.include_context:
|
219
228
|
values.update(context.flatten())
|
220
229
|
|
221
230
|
return render_to_string(
|
222
|
-
self.template_name,
|
231
|
+
self.template_name,
|
232
|
+
request=context.request if hasattr(context, "request") else None,
|
233
|
+
context=values,
|
223
234
|
)
|
224
235
|
|
225
236
|
|
@@ -416,3 +427,71 @@ def fieldset_line_classes(context: Context) -> str:
|
|
416
427
|
)
|
417
428
|
|
418
429
|
return " ".join(set(classes))
|
430
|
+
|
431
|
+
|
432
|
+
@register.simple_tag(takes_context=True)
|
433
|
+
def action_item_classes(context: Context, action: UnfoldAction) -> str:
|
434
|
+
classes = [
|
435
|
+
"border",
|
436
|
+
"-ml-px",
|
437
|
+
"max-md:first:rounded-t",
|
438
|
+
"max-md:last:rounded-b",
|
439
|
+
"md:first:rounded-l",
|
440
|
+
"md:last:rounded-r",
|
441
|
+
]
|
442
|
+
|
443
|
+
if "variant" not in action:
|
444
|
+
variant = ActionVariant.DEFAULT
|
445
|
+
else:
|
446
|
+
variant = action["variant"]
|
447
|
+
|
448
|
+
if variant == ActionVariant.PRIMARY:
|
449
|
+
classes.extend(
|
450
|
+
[
|
451
|
+
"border-primary-600",
|
452
|
+
"bg-primary-600",
|
453
|
+
"text-white",
|
454
|
+
]
|
455
|
+
)
|
456
|
+
elif variant == ActionVariant.DANGER:
|
457
|
+
classes.extend(
|
458
|
+
[
|
459
|
+
"border-red-600",
|
460
|
+
"bg-red-600",
|
461
|
+
"text-white",
|
462
|
+
]
|
463
|
+
)
|
464
|
+
elif variant == ActionVariant.SUCCESS:
|
465
|
+
classes.extend(
|
466
|
+
[
|
467
|
+
"border-green-600",
|
468
|
+
"bg-green-600",
|
469
|
+
"text-white",
|
470
|
+
]
|
471
|
+
)
|
472
|
+
elif variant == ActionVariant.INFO:
|
473
|
+
classes.extend(
|
474
|
+
[
|
475
|
+
"border-blue-600",
|
476
|
+
"bg-blue-600",
|
477
|
+
"text-white",
|
478
|
+
]
|
479
|
+
)
|
480
|
+
elif variant == ActionVariant.WARNING:
|
481
|
+
classes.extend(
|
482
|
+
[
|
483
|
+
"border-orange-600",
|
484
|
+
"bg-orange-600",
|
485
|
+
"text-white",
|
486
|
+
]
|
487
|
+
)
|
488
|
+
else:
|
489
|
+
classes.extend(
|
490
|
+
[
|
491
|
+
"border-base-200",
|
492
|
+
"hover:text-primary-600",
|
493
|
+
"dark:border-base-700",
|
494
|
+
]
|
495
|
+
)
|
496
|
+
|
497
|
+
return " ".join(set(classes))
|
@@ -16,6 +16,7 @@ from django.contrib.admin.views.main import (
|
|
16
16
|
)
|
17
17
|
from django.core.exceptions import ObjectDoesNotExist
|
18
18
|
from django.db import models
|
19
|
+
from django.db.models import Model
|
19
20
|
from django.forms import Form
|
20
21
|
from django.http import HttpRequest
|
21
22
|
from django.template import Library
|
@@ -26,13 +27,13 @@ from django.utils.html import format_html
|
|
26
27
|
from django.utils.safestring import SafeText, mark_safe
|
27
28
|
from django.utils.translation import gettext_lazy as _
|
28
29
|
|
29
|
-
from
|
30
|
+
from unfold.utils import (
|
30
31
|
display_for_field,
|
31
32
|
display_for_header,
|
32
33
|
display_for_label,
|
33
34
|
display_for_value,
|
34
35
|
)
|
35
|
-
from
|
36
|
+
from unfold.widgets import UnfoldBooleanWidget
|
36
37
|
|
37
38
|
register = Library()
|
38
39
|
|
@@ -336,23 +337,22 @@ def items_for_result(cl: ChangeList, result: HttpRequest, form) -> SafeText:
|
|
336
337
|
|
337
338
|
class UnfoldResultList(ResultList):
|
338
339
|
def __init__(
|
339
|
-
self,
|
340
|
+
self,
|
341
|
+
instance: Model,
|
342
|
+
form: Optional[Form],
|
343
|
+
*items: Any,
|
340
344
|
) -> None:
|
341
|
-
self.
|
345
|
+
self.instance = instance
|
342
346
|
super().__init__(form, *items)
|
343
347
|
|
344
348
|
|
345
349
|
def results(cl: ChangeList):
|
346
350
|
if cl.formset:
|
347
351
|
for res, form in zip(cl.result_list, cl.formset.forms):
|
348
|
-
|
349
|
-
pk_value = getattr(res, pk)
|
350
|
-
yield UnfoldResultList(pk_value, form, items_for_result(cl, res, form))
|
352
|
+
yield UnfoldResultList(res, form, items_for_result(cl, res, form))
|
351
353
|
else:
|
352
354
|
for res in cl.result_list:
|
353
|
-
|
354
|
-
pk_value = getattr(res, pk)
|
355
|
-
yield UnfoldResultList(pk_value, None, items_for_result(cl, res, None))
|
355
|
+
yield UnfoldResultList(res, None, items_for_result(cl, res, None))
|
356
356
|
|
357
357
|
|
358
358
|
def result_list(context: dict[str, Any], cl: ChangeList) -> dict[str, Any]:
|
unfold/views.py
CHANGED
@@ -1,8 +1,21 @@
|
|
1
1
|
from typing import Any
|
2
2
|
|
3
|
+
import django
|
4
|
+
from django.contrib.admin.views.main import ERROR_FLAG, PAGE_VAR
|
5
|
+
from django.contrib.admin.views.main import ChangeList as BaseChangeList
|
3
6
|
from django.contrib.auth.mixins import PermissionRequiredMixin
|
4
7
|
|
5
|
-
from .exceptions import UnfoldException
|
8
|
+
from unfold.exceptions import UnfoldException
|
9
|
+
|
10
|
+
|
11
|
+
class ChangeList(BaseChangeList):
|
12
|
+
def __init__(self, request, *args, **kwargs):
|
13
|
+
super().__init__(request, *args, **kwargs)
|
14
|
+
|
15
|
+
if django.VERSION < (5, 0):
|
16
|
+
self.filter_params = dict(request.GET.lists())
|
17
|
+
self.filter_params.pop(PAGE_VAR, None)
|
18
|
+
self.filter_params.pop(ERROR_FLAG, None)
|
6
19
|
|
7
20
|
|
8
21
|
class UnfoldModelAdminViewMixin(PermissionRequiredMixin):
|
@@ -1,75 +0,0 @@
|
|
1
|
-
Metadata-Version: 2.3
|
2
|
-
Name: django-unfold
|
3
|
-
Version: 0.49.1
|
4
|
-
Summary: Modern Django admin theme for seamless interface development
|
5
|
-
License: MIT
|
6
|
-
Keywords: django,admin,tailwind,theme
|
7
|
-
Requires-Python: >=3.9
|
8
|
-
Classifier: Environment :: Web Environment
|
9
|
-
Classifier: Framework :: Django
|
10
|
-
Classifier: Intended Audience :: Developers
|
11
|
-
Classifier: License :: OSI Approved :: MIT License
|
12
|
-
Classifier: Operating System :: OS Independent
|
13
|
-
Classifier: Programming Language :: Python
|
14
|
-
Classifier: Programming Language :: Python :: 3
|
15
|
-
Classifier: Programming Language :: Python :: 3.9
|
16
|
-
Classifier: Programming Language :: Python :: 3.10
|
17
|
-
Classifier: Programming Language :: Python :: 3.11
|
18
|
-
Classifier: Programming Language :: Python :: 3.12
|
19
|
-
Classifier: Programming Language :: Python :: 3.13
|
20
|
-
Requires-Dist: django (>=3.2)
|
21
|
-
Project-URL: Homepage, https://unfoldadmin.com
|
22
|
-
Project-URL: Repository, https://github.com/unfoldadmin/django-unfold
|
23
|
-
Description-Content-Type: text/markdown
|
24
|
-
|
25
|
-

|
26
|
-
|
27
|
-
## Unfold Django Admin Theme
|
28
|
-
|
29
|
-
[](https://pypi.org/project/django-unfold/)
|
30
|
-
[](https://github.com/unfoldadmin/django-unfold/actions?query=workflow%3Arelease)
|
31
|
-

|
32
|
-

|
33
|
-
|
34
|
-
Unfold is a theme for Django admin that incorporates common best practices for building full-fledged admin areas. It is designed to work on top of the default administration provided by Django.
|
35
|
-
|
36
|
-
- **Documentation:** Full docs are available at [unfoldadmin.com](https://unfoldadmin.com?utm_medium=github&utm_source=unfold).
|
37
|
-
- **Unfold:** Demo site is available at [unfoldadmin.com](https://unfoldadmin.com?utm_medium=github&utm_source=unfold).
|
38
|
-
- **Formula:** Repository with demo implementation at [github.com/unfoldadmin/formula](https://github.com/unfoldadmin/formula?utm_medium=github&utm_source=unfold).
|
39
|
-
- **Turbo:** Django & Next.js boilerplate implementing Unfold at [github.com/unfoldadmin/turbo](https://github.com/unfoldadmin/turbo?utm_medium=github&utm_source=unfold).
|
40
|
-
- **Discord:** Join the Unfold community on [Discord](https://discord.gg/9sQj9MEbNz).
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
## Are you using Unfold and need help?
|
45
|
-
|
46
|
-
Have you decided to start using Unfold but don’t have time to make the switch from the native Django admin? [Get in touch with us](https://unfoldadmin.com/consulting?utm_medium=github&utm_source=unfold) and let’s supercharge your development with our expertise.
|
47
|
-
|
48
|
-
## Features
|
49
|
-
|
50
|
-
- **Visual**: Provides a new user interface based on the Tailwind CSS framework.
|
51
|
-
- **Sidebar:** Simplifies the creation of sidebar navigation with icons, collapsibles, and more.
|
52
|
-
- **Dark mode:** Supports both light and dark mode versions.
|
53
|
-
- **Actions:** Offers multiple ways to define actions within different parts of the admin interface.
|
54
|
-
- **Filters:** Custom dropdowns, autocomplete, numeric, datetime, and text fields.
|
55
|
-
- **Dashboard:** Includes helpers for creating custom dashboard pages.
|
56
|
-
- **Components:** Reusable UI components such as cards, buttons, and charts.
|
57
|
-
- **WYSIWYG widget:** Built-in support for WYSIWYG (Trix).
|
58
|
-
- **Array widget:** Built-in widget for `django.contrib.postgres.fields.ArrayField`.
|
59
|
-
- **Inline tabs:** Groups inlines into tab navigation in the change form.
|
60
|
-
- **Model tabs:** Allows defining custom tab navigation for models.
|
61
|
-
- **Fieldset tabs:** Merges multiple fieldsets into tabs in the change form.
|
62
|
-
- **Sortable inlines:** Allows sorting inlines by dragging and dropping.
|
63
|
-
- **Environment label**: Distinguishes between environments by displaying a label.
|
64
|
-
- **Nonrelated inlines**: Displays nonrelated models as inlines in the change form.
|
65
|
-
- **Favicons**: Built-in support for configuring various site favicons.
|
66
|
-
- **Themes:** Allows customization of color scheme, background color, border radius, and more.
|
67
|
-
- **Font colors:** Adjusts font colors for better readability.
|
68
|
-
- **Changeform modes:** Displays fields in compressed mode in the change form.
|
69
|
-
- **Language switcher:** Change language directly from the admin area.
|
70
|
-
- **Parallel admin**: Supports [running the default admin](https://unfoldadmin.com/blog/migrating-django-admin-unfold/?utm_medium=github&utm_source=unfold) alongside Unfold.
|
71
|
-
- **Third party packages:** Default support for multiple popular applications.
|
72
|
-
- **Configuration:** Most basic options can be changed in `settings.py`.
|
73
|
-
- **Dependencies:** Fully based on `django.contrib.admin`.
|
74
|
-
- **VS Code**: Project configuration and development container included.
|
75
|
-
|