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.
Files changed (36) hide show
  1. django_unfold-0.51.0.dist-info/METADATA +81 -0
  2. {django_unfold-0.49.1.dist-info → django_unfold-0.51.0.dist-info}/RECORD +34 -30
  3. {django_unfold-0.49.1.dist-info → django_unfold-0.51.0.dist-info}/WHEEL +1 -1
  4. unfold/admin.py +4 -0
  5. unfold/contrib/filters/admin/dropdown_filters.py +1 -0
  6. unfold/contrib/filters/admin/mixins.py +10 -4
  7. unfold/contrib/filters/forms.py +2 -2
  8. unfold/dataclasses.py +3 -0
  9. unfold/decorators.py +8 -0
  10. unfold/enums.py +10 -0
  11. unfold/mixins/action_model_admin.py +4 -0
  12. unfold/sections.py +82 -0
  13. unfold/settings.py +1 -0
  14. unfold/sites.py +3 -0
  15. unfold/static/admin/js/inlines.js +18 -5
  16. unfold/static/unfold/css/styles.css +1 -1
  17. unfold/static/unfold/js/select2.init.js +29 -0
  18. unfold/styles.css +1 -1
  19. unfold/templates/admin/change_list.html +16 -16
  20. unfold/templates/admin/change_list_results.html +38 -40
  21. unfold/templates/admin/filter.html +2 -2
  22. unfold/templates/unfold/components/card.html +1 -1
  23. unfold/templates/unfold/components/table.html +42 -26
  24. unfold/templates/unfold/helpers/change_list_filter_actions.html +1 -1
  25. unfold/templates/unfold/helpers/empty_results.html +35 -0
  26. unfold/templates/unfold/helpers/tab_action.html +24 -19
  27. unfold/templates/unfold/helpers/tab_actions.html +19 -0
  28. unfold/templates/unfold/helpers/tab_items.html +47 -0
  29. unfold/templates/unfold/helpers/tab_list.html +3 -66
  30. unfold/templates/unfold/layouts/skeleton.html +1 -2
  31. unfold/templatetags/unfold.py +81 -2
  32. unfold/templatetags/unfold_list.py +10 -10
  33. unfold/views.py +14 -1
  34. django_unfold-0.49.1.dist-info/METADATA +0 -75
  35. unfold/contrib/filters/admin.py +0 -619
  36. {django_unfold-0.49.1.dist-info → django_unfold-0.51.0.dist-info}/LICENSE.md +0 -0
@@ -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"], request=context.request
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, request=context.request, context=values
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 ..utils import (
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 ..widgets import UnfoldBooleanWidget
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, instance_pk: Union[int, str], form: Optional[Form], *items: Any
340
+ self,
341
+ instance: Model,
342
+ form: Optional[Form],
343
+ *items: Any,
340
344
  ) -> None:
341
- self.instance_pk = instance_pk
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
- pk = cl.lookup_opts.pk.attname
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
- pk = cl.lookup_opts.pk.attname
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
- ![screenshot](https://github.com/user-attachments/assets/87aaad04-f454-42aa-b9ac-e14d41f189ac)
26
-
27
- ## Unfold Django Admin Theme
28
-
29
- [![PyPI - Version](https://img.shields.io/pypi/v/django-unfold.svg?style=for-the-badge)](https://pypi.org/project/django-unfold/)
30
- [![Build](https://img.shields.io/github/actions/workflow/status/unfoldadmin/django-unfold/release.yml?style=for-the-badge)](https://github.com/unfoldadmin/django-unfold/actions?query=workflow%3Arelease)
31
- ![Pre Commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white&style=for-the-badge)
32
- ![Code Style - Ruff](https://img.shields.io/badge/code%20style-ruff-30173D.svg?style=for-the-badge)
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
-