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
@@ -0,0 +1,81 @@
1
+ Metadata-Version: 2.3
2
+ Name: django-unfold
3
+ Version: 0.51.0
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 (>=4.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
+ Transform your Django admin into a powerful, modern administrative interface with Unfold. This open-source theme enhances Django's default admin with beautiful design, advanced features, and developer-friendly customization options. Built on proven best practices, Unfold seamlessly integrates with your existing Django admin while providing all the tools needed to create sophisticated administrative areas that both developers and end-users will love.
35
+
36
+ - **Documentation:** The full documentation is available at [unfoldadmin.com](https://unfoldadmin.com?utm_medium=github&utm_source=unfold).
37
+ - **Unfold:** The demo site is available at [unfoldadmin.com](https://unfoldadmin.com?utm_medium=github&utm_source=unfold).
38
+ - **Formula:** A repository with a demo implementation is available at [github.com/unfoldadmin/formula](https://github.com/unfoldadmin/formula?utm_medium=github&utm_source=unfold).
39
+ - **Turbo:** A Django & Next.js boilerplate implementing Unfold is available at [github.com/unfoldadmin/turbo](https://github.com/unfoldadmin/turbo?utm_medium=github&utm_source=unfold).
40
+ - **Discord:** Join our Unfold community on [Discord](https://discord.gg/9sQj9MEbNz).
41
+
42
+ ## Django & Unfold Development Services
43
+
44
+ Need assistance with implementing Unfold or require custom Django development? Professional consulting and development services are available to help transform your Django admin interface and enhance your web applications. Whether migrating from the native Django admin to Unfold or seeking expert technical guidance, reach out to discuss your project requirements and explore development possibilities. [Get in touch](https://unfoldadmin.com/consulting?utm_medium=github&utm_source=unfold) to learn more about available services.
45
+
46
+ ## Fresh Features & Enhancements
47
+
48
+ - **Autocomplete filters:** Enhance filter functionality with built-in autocomplete support
49
+ - **Site dropdown:** Configurable dropdown menu in the header area for managing custom navigation links
50
+ - **Dropdown actions:** Organize action items in customizable dropdown menus
51
+ - **Custom tab navigation:** Create flexible, structured tab navigation with customizable routing
52
+
53
+
54
+ ## Core Features & Capabilities
55
+
56
+ - **Visual Interface**: Provides a modern user interface based on the Tailwind CSS framework.
57
+ - **Sidebar Navigation**: Simplifies the creation of sidebar menus with icons, collapsible sections, and more.
58
+ - **Dark Mode Support**: Includes both light and dark mode themes.
59
+ - **Flexible Actions**: Provides multiple ways to define actions throughout the admin interface.
60
+ - **Advanced Filters**: Features custom dropdowns, autocomplete, numeric, datetime, and text field filters.
61
+ - **Dashboard Tools**: Includes helpers for building custom dashboard pages.
62
+ - **UI Components**: Offers reusable interface components such as cards, buttons, and charts.
63
+ - **WYSIWYG Editor**: Built-in support for WYSIWYG editing through Trix.
64
+ - **Array widget:** Built-in widget for `django.contrib.postgres.fields.ArrayField`
65
+ - **Inline tabs:** Group inlines into tab navigation in the change form
66
+ - **Model tabs:** Allow defining custom tab navigation for models
67
+ - **Fieldset tabs:** Merge multiple fieldsets into tabs in the change form
68
+ - **Sortable inlines:** Allow sorting inlines by dragging and dropping
69
+ - **Environment label:** Distinguish between environments by displaying a label
70
+ - **Nonrelated inlines:** Display nonrelated models as inlines in the change form
71
+ - **Favicons:** Built-in support for configuring various site favicons
72
+ - **Themes:** Allow customization of color scheme, background color, border radius, and more
73
+ - **Font colors:** Adjust font colors for better readability
74
+ - **Changeform modes:** Display fields in compressed mode in the change form
75
+ - **Language switcher:** Allow changing language directly from the admin area
76
+ - **Parallel admin:** Supports [running the default admin](https://unfoldadmin.com/blog/migrating-django-admin-unfold/?utm_medium=github&utm_source=unfold) alongside Unfold.
77
+ - **Third-party packages:** Provides default support for multiple popular applications.
78
+ - **Configuration:** Allows basic options to be changed in `settings.py`.
79
+ - **Dependencies:** Built entirely on `django.contrib.admin`.
80
+ - **VS Code:** Project configuration and development container included.
81
+
@@ -1,5 +1,5 @@
1
1
  unfold/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- unfold/admin.py,sha256=JOT4AbbCcGKDi_Qwi_yuFngkLbo78SHd-aHiHNLaI8M,6093
2
+ unfold/admin.py,sha256=_dshyJ1LhGZhcx-eRdny9l1OEcIrqxmKzQzpfZcQAY4,6205
3
3
  unfold/apps.py,sha256=SlBXPYrUd2uXn67qFbRvbXSUk3XFWrF4-5WELgDCvho,381
4
4
  unfold/checks.py,sha256=8I3i4xR_KgyJdpQyZUZzKNeyYf-sNzg6PAlsREuMfgI,1664
5
5
  unfold/components.py,sha256=vqkQzseYUvLXDohmTVAlbKopALjyX4WA9yglvdfhqu4,1283
@@ -8,13 +8,12 @@ unfold/contrib/filters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
8
8
  unfold/contrib/filters/admin/__init__.py,sha256=2pyv21jMqQVC8pnP8FOERHRH2hgZSOLQzV0BUn5wjHo,1216
9
9
  unfold/contrib/filters/admin/autocomplete_filters.py,sha256=Jh3m3iQ8YubZRQDVzHPGfpk9RulOhHkZc0N7L6KV9wc,514
10
10
  unfold/contrib/filters/admin/datetime_filters.py,sha256=cVari_7jsfeYxJoRBhcAUOr6v9XdtDtMuMs-S1Irafo,7757
11
- unfold/contrib/filters/admin/dropdown_filters.py,sha256=SycJ6zgZbR4isy16oxiD0ZpAX_WuKUYNcifJG71b8Sw,3323
12
- unfold/contrib/filters/admin/mixins.py,sha256=VMFyXz9yXGjOphB2pllKJSbJGnWkIpY33iq56OoG6Cg,4767
11
+ unfold/contrib/filters/admin/dropdown_filters.py,sha256=YiPLakTIzLuojULfpctFV0aP8DwfWLDnU-lcjoK2qnE,3354
12
+ unfold/contrib/filters/admin/mixins.py,sha256=djaM5kxQFvl64GkNnhbCyo78UVNhDb0CIDiSNUXkUGo,4943
13
13
  unfold/contrib/filters/admin/numeric_filters.py,sha256=8GNmesgMmMIfEZb2IrGbaBoJuvB2FpIc7wPIPBpHat4,6420
14
14
  unfold/contrib/filters/admin/text_filters.py,sha256=NXyKm0Ed24N9pNfR7Dys5kTpZ_V5FUurdxk7KDMdRIg,2084
15
- unfold/contrib/filters/admin.py,sha256=TvgtP5PZVMD9JJ22YdjC1CyH0Q9oxZON5zVXq2yGZVU,21127
16
15
  unfold/contrib/filters/apps.py,sha256=wEySJy0gMLzFLb9XNKE-RexiO05X7NaQ5QmxZyziJ_k,136
17
- unfold/contrib/filters/forms.py,sha256=lIhrmYv6rXXIT14xaChDpfzklUb-B9w8yz5YgdEegOg,7238
16
+ unfold/contrib/filters/forms.py,sha256=_eHiUaTKltkZ3pWG77LiWYnEVMC-2A-wj1LMLkcCPvc,7233
18
17
  unfold/contrib/filters/static/unfold/filters/css/nouislider.min.css,sha256=rddL_jOGGVEY6wR-aw0VYovAfz5fPeAIsulrlSNb1hc,4221
19
18
  unfold/contrib/filters/static/unfold/filters/js/DateTimeShortcuts.js,sha256=jgFNBDf6aHvUlyv0LEDHggXO-xA8pWOCWFWcVupdA30,19332
20
19
  unfold/contrib/filters/static/unfold/filters/js/admin-numeric-filter.js,sha256=nTkiiJk4Abn9d6KigxPSEsereFhFq-v5n_boiiY1eII,1668
@@ -72,21 +71,23 @@ unfold/contrib/simple_history/templates/simple_history/object_history.html,sha25
72
71
  unfold/contrib/simple_history/templates/simple_history/object_history_form.html,sha256=JKCe-QTBZMB2ol5LPiX3gNuNxFpi_rqlXC9X92PFBPE,2296
73
72
  unfold/contrib/simple_history/templates/simple_history/object_history_list.html,sha256=ls_xEAAgGzbu0IXdjZk7scEyEJx0S7i3Khr9ND98gzY,6842
74
73
  unfold/contrib/simple_history/templates/simple_history/submit_line.html,sha256=y8BleGHPNztA_R37rTB-zjJ68uDbE8flYSvMD0Jfl5Y,1734
75
- unfold/dataclasses.py,sha256=p3sqaIRfmGYEMq_-cSQIRYdsTeuqgiJ4ge_neQQrpd4,618
76
- unfold/decorators.py,sha256=xofDxfJhVSmeyTh3fXiCXZtUKliuJOlxCQVQg3f1Fss,3740
74
+ unfold/dataclasses.py,sha256=a-9INnkCAIcnMgoffTcB1rxWCJH33AjhMCWIGWnjWbI,719
75
+ unfold/decorators.py,sha256=BZC6wr04lIBbK-0zylWxzgMqFWAw8slDaC4ccN8AqJI,3975
76
+ unfold/enums.py,sha256=9sTfyEycMWeoGPBa-ft6ZhQGnW1vkFg108RMBVf9nko,187
77
77
  unfold/exceptions.py,sha256=gcCj1ox61E137bk_0Cqy4YC3SttdPgB-fiJUqpmyHSE,43
78
78
  unfold/fields.py,sha256=J3goIMlP_XOmQ85Xgh2v5MylXSP1o5I7o9_So2FQn2k,7461
79
79
  unfold/forms.py,sha256=BKv7eCbv29eCIuf1d_ZBmD4-_OIIzRaopiFd2nKbXNY,4520
80
80
  unfold/mixins/__init__.py,sha256=YlhoDs9Y_DXQ8Ejr3enxuHMS1-Ij9fwukxNwpeOS4Co,190
81
- unfold/mixins/action_model_admin.py,sha256=FI326hzuGzoPBvQrl9UF-mGcczMhJJaW5Qcb43_hH8I,11803
81
+ unfold/mixins/action_model_admin.py,sha256=BPajuTGf7zAaZOqIq4shX8VQ3NTxWQpedvG58fmCTjk,12036
82
82
  unfold/mixins/base_model_admin.py,sha256=PR4eqU48yB4CNy9Bjd7fjxbOFiFpZM4etYmBOSaRX_M,4140
83
83
  unfold/overrides.py,sha256=ERVY9boZiXgjDYcTEZcIp7KWoeBZ45VM_zN31yAOjyQ,2922
84
- unfold/settings.py,sha256=5gs0iewBoUUrsF9LHHqcGOhW1HnyfZWY_zXuATjJOzE,2671
85
- unfold/sites.py,sha256=iwpJ9Qykxe0q4-alGE_07bJdBSpmIeTDxZil-C_vWSc,16054
84
+ unfold/sections.py,sha256=Lcg3xCZ76fqjm4vD4x7YdE5VsbTKluL-sX5QTEBlHxA,2379
85
+ unfold/settings.py,sha256=3ICha2I0oSaHhajG8159nHdNTYJInBtRQq9VziWKYKs,2709
86
+ unfold/sites.py,sha256=Pl8voDdMH_9RV1n3XmSz84T6OE8yDUAqNwlr-kPH1n8,16179
86
87
  unfold/static/admin/js/admin/RelatedObjectLookups.js,sha256=alI0-yq7YPDJJJn-yg1ce79-Cv88yQDUrfaGqFZnsaY,9048
87
- unfold/static/admin/js/inlines.js,sha256=gxmQEUlJ9yasELjz9qpluogFZB-bD1KJfHs4PI7UjsA,14687
88
+ unfold/static/admin/js/inlines.js,sha256=74QODSKEkpKse4bft4wIFZquROcr2-hVTt9CEWOIJak,15061
88
89
  unfold/static/unfold/css/simplebar.css,sha256=5LLaEM11pKi6JFCOLt4XKuZxTpT9rpdq_tNlaQytFlU,4647
89
- unfold/static/unfold/css/styles.css,sha256=ORq4t5sGDPl16B-05v-3ahusgoLVu9r6pH2kiYuNbPY,158172
90
+ unfold/static/unfold/css/styles.css,sha256=iMPVdCjI66jaAgjmHRV6n0jV8ssKCYa-v72mfbRlmo0,159966
90
91
  unfold/static/unfold/fonts/inter/Inter-Bold.woff2,sha256=-oiBJ7baAVtlVp8DUfO1w5GtkokElR8cIOn4RiqNleo,114840
91
92
  unfold/static/unfold/fonts/inter/Inter-Medium.woff2,sha256=D_PpRhThST61VjFP0keubEqFp3g7TMhr5TmUDPg_Kkg,114348
92
93
  unfold/static/unfold/fonts/inter/Inter-Regular.woff2,sha256=4G9rG8VTqupORmgCPtCrChRxKcMQf1Ebx9A9NhsK4IU,111268
@@ -102,9 +103,9 @@ unfold/static/unfold/js/alpine.sort.js,sha256=q6LxgConwu8M8R03mZSBcsKwJv6fF7oomP
102
103
  unfold/static/unfold/js/app.js,sha256=mxCSV8gZvRLHab-_Xm_229NtQ9IX-59vS_GKWTp9liM,7748
103
104
  unfold/static/unfold/js/chart.js,sha256=22W6cFERR-CElMOKRgMMicueMVP0Vf7FBEBYH8Z8tCk,200633
104
105
  unfold/static/unfold/js/htmx.js,sha256=acrv0NqSJpBm5yXX_hdeJrnVDJYuMFZFnAxHcVTNudM,50918
105
- unfold/static/unfold/js/select2.init.js,sha256=siSDCwzy2PsOwA0Kj26JA_ELBtZlS70O8D8f1qTMmqg,291
106
+ unfold/static/unfold/js/select2.init.js,sha256=gXZngZh-l5ID2-VmndpGseNi6A0zKB18UgPyCor68CU,1040
106
107
  unfold/static/unfold/js/simplebar.js,sha256=t-uG1FAD6ZoiMeN--wac0XRS7SxoDVG6zvRnGuEp7X8,27176
107
- unfold/styles.css,sha256=XrdDgMYgyCw77ieNcxhHcwhkRLBvQCa-5PBf66JLZvU,18796
108
+ unfold/styles.css,sha256=yp_oUco8yAJa-lJiioMAoORC-JGCMHFrhRjuk1aEYog,18786
108
109
  unfold/templates/admin/actions.html,sha256=aroIid16mORcx-0p8O2dOoWupEoTGX66pt-PAXjSYZ0,3063
109
110
  unfold/templates/admin/app_index.html,sha256=GSBry97gDcK3scTP-Fs4FXcSItRxxE87Wv4sDtMTlbc,1244
110
111
  unfold/templates/admin/app_list.html,sha256=VtntgHpbZdXbt_HXBLAtbuMdz1alS7F_S7eG37M5Rig,2855
@@ -114,15 +115,15 @@ unfold/templates/admin/base.html,sha256=3xQmoD_7cu2UlgEdvnt7v_CibT9t1Iul0b-VU2Aw
114
115
  unfold/templates/admin/base_site.html,sha256=UOsecaCycpyn_ygJNIKO7MQtDFJuHv--r83-mzaVY30,300
115
116
  unfold/templates/admin/change_form.html,sha256=LfeAeLYpJvNhOMJWQFeb9oSrAznlB4pnFrqTVMCIy4o,5340
116
117
  unfold/templates/admin/change_form_object_tools.html,sha256=eyeH-i2HgEM0Yi-OJA2D1VnKJyC19A_my1IDGxxoP8Y,593
117
- unfold/templates/admin/change_list.html,sha256=V2DgxlGaQvcOS1qAxe4no1EJCq-9nIOa10kYLkcE2Ag,5008
118
+ unfold/templates/admin/change_list.html,sha256=AhGUdt-S3m30WhSraWnBdLwZQ1JU9yZeVDL0WDqCEMI,5164
118
119
  unfold/templates/admin/change_list_object_tools.html,sha256=cmMiT2nT20Ph5yfpj9aHPr76Z-JP4aSXp0o-Rnad28s,147
119
- unfold/templates/admin/change_list_results.html,sha256=UweKSz7jKJ6apEHv2MrGq2xf-o1PKjMuKqqitdb-GSk,7624
120
+ unfold/templates/admin/change_list_results.html,sha256=n64K5ocS62kujxzzkojzOx4jJuiYcO8r4mcJfcsCQAs,7931
120
121
  unfold/templates/admin/date_hierarchy.html,sha256=Jl_Vk05fXvsSvod5Dw2p3KhpCQGjtSX1zqlNjjkBFR4,1411
121
122
  unfold/templates/admin/delete_confirmation.html,sha256=yT_NHbFHZEjkSCaGVcM52GCG-FDmWiJdTFLbq9CBCx4,4619
122
123
  unfold/templates/admin/delete_selected_confirmation.html,sha256=QR0JhrPR8YI8KpQnB3xyrKxaui-_pEQmfaMDbcXjjZ0,4391
123
124
  unfold/templates/admin/edit_inline/stacked.html,sha256=-ASy7Jd0SwWBDxurucbus86YT2AokJEcCUrqPlHVDQA,7644
124
125
  unfold/templates/admin/edit_inline/tabular.html,sha256=FBgzUb-U0cZCN28-cpHzRSyPE6bgseD_r3MY1AP0nGQ,2813
125
- unfold/templates/admin/filter.html,sha256=ZnnJbg-9e6LM0OyKJW7V-DA7mmxkGhJeOpEfnM5JGM8,1998
126
+ unfold/templates/admin/filter.html,sha256=0B_hpLybHw1wUPPCN3KJvoWrx03iFeqP8m1LRCjnLlQ,2012
126
127
  unfold/templates/admin/includes/fieldset.html,sha256=gX-dc-jPLswk21XSKUXzAU8WFl3CFfeVrIAU2bviPyg,812
127
128
  unfold/templates/admin/includes/object_delete_summary.html,sha256=FgwfapZCKWtnFtTHqh1MRuxxLot4bAw92WCcR_V8ImI,444
128
129
  unfold/templates/admin/index.html,sha256=JnNDpNKqFKVKMQvpUQo6ddcFqGadK5g78pxpKAHLuMU,583
@@ -137,7 +138,7 @@ unfold/templates/registration/logged_out.html,sha256=GgLzqmOGpiw5FcA-Aw_T6YvhYHh
137
138
  unfold/templates/registration/password_change_done.html,sha256=9HDpSraz3Kxdy0Fghbn-Lv0GAtpPgG6cuO7fvfMiYg8,1077
138
139
  unfold/templates/registration/password_change_form.html,sha256=EgakVWzpQUEJKQS0AOfk8O_CY1bKbyWXSUuBaxtQEdU,2232
139
140
  unfold/templates/unfold/components/button.html,sha256=TABo79ppuGlm2ENvRs6L3Vne8B5_9he_OhZTnPMiitQ,473
140
- unfold/templates/unfold/components/card.html,sha256=04xD3Cn5-2OUouoQ71EkS6t0AgAx4OeGaeOf85wPp_U,1115
141
+ unfold/templates/unfold/components/card.html,sha256=FVLN7kQZqMd_uhEi1LpiN9FUxZCa4RgGHYGmofCtQro,1141
141
142
  unfold/templates/unfold/components/chart/bar.html,sha256=nDdDCUXvFd793OpNgNPQo0vBmvYngMsQyPHVTf1vfOw,297
142
143
  unfold/templates/unfold/components/chart/cohort.html,sha256=elZj9e9E9cfVey_9LSOaDoVSE3Wn3BagSrwIXRSFadM,2354
143
144
  unfold/templates/unfold/components/chart/line.html,sha256=DHaZUFTlCs5cX7ioYdTzoN4ITHWNcEoNSUp7v3hlo_E,298
@@ -147,7 +148,7 @@ unfold/templates/unfold/components/icon.html,sha256=Qlhcf41FOwNVJ-nvA0RJ_Dn6JW6P
147
148
  unfold/templates/unfold/components/navigation.html,sha256=NCPFXM1Q__2LoIyNNYbhhZZPtdw3eLvmc9vlhnm9mhg,887
148
149
  unfold/templates/unfold/components/progress.html,sha256=BnH2uC_ZL5ITvMjHiHoM0gjtbRTLNU1-tFcfCuJO0BE,808
149
150
  unfold/templates/unfold/components/separator.html,sha256=yvHywT_MFkx5dNC2K53OFHRGxLDsEjRpptujXyGeoTY,168
150
- unfold/templates/unfold/components/table.html,sha256=_mIfauxVCt7gFC8CJpDdBp3TaGc99Lu4QLg5D8597-s,2022
151
+ unfold/templates/unfold/components/table.html,sha256=awXLt0diLeUAk1akVvyXiNApExtENR-MP-lf4MQrWTs,3075
151
152
  unfold/templates/unfold/components/text.html,sha256=-GjxvdiaBQIaNfPSzT6SSIwnc3R27FkSDQMoF3FDPso,102
152
153
  unfold/templates/unfold/components/title.html,sha256=aMYSO30ybFYqPnqwlJVh2uNmcgnVrRycZkHTjJTjpX8,171
153
154
  unfold/templates/unfold/components/tracker.html,sha256=-PvDHdAAB2G5mKXpQUtljWJYhhavsa1aEoBvLrCiCJo,284
@@ -161,7 +162,7 @@ unfold/templates/unfold/helpers/boolean.html,sha256=kcSZr3siQeBWIy_jsx1tFf4m6IB3
161
162
  unfold/templates/unfold/helpers/breadcrumb_item.html,sha256=9T6ojN7LOXIlgwSwlIwHgy5U22eQYtarCqcmzsQIoPU,201
162
163
  unfold/templates/unfold/helpers/change_list_actions.html,sha256=p1_vC2Q_Fb-gAHA8y1zzOXqqn5TPQMrQfE26PkOY_ok,656
163
164
  unfold/templates/unfold/helpers/change_list_filter.html,sha256=0l-c4H2PcDkAuzI6asAJf2rBfYavYG62F9d7yWWdkSI,1852
164
- unfold/templates/unfold/helpers/change_list_filter_actions.html,sha256=Dy8CGBPNuMJAHf1_ynGYOjLrsemQJI1vkDldKBWtSlk,1777
165
+ unfold/templates/unfold/helpers/change_list_filter_actions.html,sha256=fTlM6jyS83FhGulFYuhFVLJOGHRJV3mFCWDQnp1kp0U,1760
165
166
  unfold/templates/unfold/helpers/delete_submit_line.html,sha256=N1w_TDIDN7Spj5diuhRUVOVgz2TiSeHVK2QvBjTLv2w,665
166
167
  unfold/templates/unfold/helpers/display_header.html,sha256=rhru2GSxR0mH8_FEQuQVIS8gGGjaiWMV9f2HCPGMsaQ,1698
167
168
  unfold/templates/unfold/helpers/display_label.html,sha256=LS9DWzYjHkYLV27sZDwyXlg2sLJ0AlId9FbjnXpsbfg,317
@@ -171,6 +172,7 @@ unfold/templates/unfold/helpers/edit_inline/tabular_field.html,sha256=BRCAXdv-HB
171
172
  unfold/templates/unfold/helpers/edit_inline/tabular_heading.html,sha256=ER8R64wnKOu26WTwP4_Wxt-LRB_zRkXLhheZ_utVvKY,1523
172
173
  unfold/templates/unfold/helpers/edit_inline/tabular_row.html,sha256=Cfs2m5eh3mLcMgL0_dSAokAscgq4q19KsnUPZECmDgw,2013
173
174
  unfold/templates/unfold/helpers/edit_inline/tabular_title.html,sha256=JPSue6mD1-KZ3tiymbRrv1G2XgsSim4cT_6HhzYJaYY,2710
175
+ unfold/templates/unfold/helpers/empty_results.html,sha256=KV9DLKLURDtlkjDI88u05l6cXiOoeSv1nR4wFNIQ2hE,1933
174
176
  unfold/templates/unfold/helpers/field.html,sha256=Ds-zUHkdyxamfUCVNhxvtM0XoJg9OCA0QcsLbLWv4oo,882
175
177
  unfold/templates/unfold/helpers/field_readonly.html,sha256=4qtXjWE7SA2qZSTYLOv0lT4pQfD0TE34mvWQJY7jhS8,237
176
178
  unfold/templates/unfold/helpers/field_readonly_value.html,sha256=6DNteF8x6_tihQZVCGgz2CqB0ogsLRJhxgDep0sHguc,464
@@ -204,14 +206,16 @@ unfold/templates/unfold/helpers/site_dropdown.html,sha256=Zwg5ZGVIEHAI2h-YcWDDBz
204
206
  unfold/templates/unfold/helpers/site_icon.html,sha256=rB6oc6VBB0T7wtyGOPcrq6qepDRaA54F6-Wxtaru-ks,1297
205
207
  unfold/templates/unfold/helpers/site_logo.html,sha256=S_QJoT2qh0xw0ciaKxoT4GJ6QIH5eqgRSC0abbWWkOI,423
206
208
  unfold/templates/unfold/helpers/submit.html,sha256=4Mgf4lx7Atm8GPqD6LTJK3NA9zoSJjs9VPig7sDp8Ao,203
207
- unfold/templates/unfold/helpers/tab_action.html,sha256=qnMmPJOeMLAx64uTf1pdPq1OIKm1MQ2Et6vTU6WQb-8,2065
208
- unfold/templates/unfold/helpers/tab_list.html,sha256=ULuTZ7VaUFsgtqNr9eCb-A_Qmhp7gqt43V8sdu5fEII,5032
209
+ unfold/templates/unfold/helpers/tab_action.html,sha256=6N6Xi7XGtweS6gt0oZrVu6AIaJ9WIQSH-mpndn0CCYE,2263
210
+ unfold/templates/unfold/helpers/tab_actions.html,sha256=DMNqY1YyrNrcutOMC3J1neZZjIkPeYShp1i5xZ10nrc,695
211
+ unfold/templates/unfold/helpers/tab_items.html,sha256=Gi6cjYJ7tJWO6zSXjg8xNHY9ALpYzjQOEORusf_AZfg,3325
212
+ unfold/templates/unfold/helpers/tab_list.html,sha256=Tqkug9GyoIQ2geVKWrnnuE0bxeTRXj0MSEwwixoOGz4,436
209
213
  unfold/templates/unfold/helpers/theme_switch.html,sha256=Kh3Q8RuBWCUuY8YJLwBwd5yKzDhK6y0Ggx_ERoGEGv8,2218
210
214
  unfold/templates/unfold/helpers/userlinks.html,sha256=oZqiwCxG_zRecAbzYrr8_hQvkndVB6-liP6LEZM1UZc,863
211
215
  unfold/templates/unfold/helpers/welcomemsg.html,sha256=a7VjZ8J1mn-DAo57nhUP096SEcBOqcCWrWt2qoT0cyg,1882
212
216
  unfold/templates/unfold/layouts/base.html,sha256=e9T-vuPvrySHf23LLwRuTQXUg0Q4x-6gmT_yXghqc-I,278
213
217
  unfold/templates/unfold/layouts/base_simple.html,sha256=VigjNWnWOt_XtbahvqsroPf8mdwl7cDGbg5fEaLmG9s,1211
214
- unfold/templates/unfold/layouts/skeleton.html,sha256=cE29ydXMseyXut1k7Yme3alnUBFXhBDxT0WFZCgrvGQ,4600
218
+ unfold/templates/unfold/layouts/skeleton.html,sha256=TmZ0hX5j7McwSiYcdGGuhAjDunPDCWtPC7lDF6hbtDk,4641
215
219
  unfold/templates/unfold/templatetags/preserve_changelist_filters.html,sha256=sx2jUhogNY4emBhY8PqxQ6mXifbXQb_IQI9Hd0boJI0,111
216
220
  unfold/templates/unfold/widgets/clearable_file_input.html,sha256=4vsLRjqOmGqdU4aPSq81rc-mdRvpBr-H_bC5ScyUkEY,2231
217
221
  unfold/templates/unfold/widgets/clearable_file_input_small.html,sha256=NNlosUwhzv-3SZH9LdliL5c6fdoVNRb1JP0uHwFV-N8,2849
@@ -229,13 +233,13 @@ unfold/templates/unfold/widgets/textarea_expandable.html,sha256=Pqi2udY0FWxVA-B1
229
233
  unfold/templates/unfold/widgets/time.html,sha256=WXo2LG1v_gBZBSg-zocj7oujMKI0MWLYCIFfB04HMLQ,122
230
234
  unfold/templates/unfold/widgets/url.html,sha256=IRLgW44VTKN7UrSWeywJwaxQhfG5jhhXuT-KTadKX58,304
231
235
  unfold/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
232
- unfold/templatetags/unfold.py,sha256=C2x_fqjVCWku4WdyaD_u4UjXq9eue1CgnmEz5PCfrS8,12364
233
- unfold/templatetags/unfold_list.py,sha256=-KOU6Ib2k4gokuw_CgRooFCto8xJkiDyotbQbKAqkEY,14233
236
+ unfold/templatetags/unfold.py,sha256=dx-_6ml3Lt6AGYdl4TnDFFssLrqK0LwlcrKERlfV_GI,14462
237
+ unfold/templatetags/unfold_list.py,sha256=DTPVSM2gD59-R4bk39VOEqtzctCB2vgxOINuzHzZIho,14108
234
238
  unfold/typing.py,sha256=i7LM2LiwYTAjT5-OLDUPVn5b9X-DMmHnjlZG2toWwSE,692
235
239
  unfold/utils.py,sha256=L0oC9-j1B__BZ21M7i6rTXNbzCQaZ4T0qHYQcNupk0A,5480
236
- unfold/views.py,sha256=nqv-meiwGtCeET2r8WBVyijWnE94Dssc4QmdUVMMcEM,997
240
+ unfold/views.py,sha256=FuYnMrlg6SegLUDDN6An__yZj8rchD_iBK8myieYhkA,1492
237
241
  unfold/widgets.py,sha256=esW1wxdbZwUhF31ensitBF8_6kVq_Gp0_iDgv6F5Rr0,20246
238
- django_unfold-0.49.1.dist-info/LICENSE.md,sha256=Ltk_quRyyvV3J5v3brtOqmibeZSw2Hrb8bY1W3ya0Ik,1077
239
- django_unfold-0.49.1.dist-info/METADATA,sha256=TV-wBErjvceg-rCW_Qe4rP748lxMQJq2u2ggVrZmD6M,4840
240
- django_unfold-0.49.1.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
241
- django_unfold-0.49.1.dist-info/RECORD,,
242
+ django_unfold-0.51.0.dist-info/LICENSE.md,sha256=Ltk_quRyyvV3J5v3brtOqmibeZSw2Hrb8bY1W3ya0Ik,1077
243
+ django_unfold-0.51.0.dist-info/METADATA,sha256=SsSBDtZp3pGZVgBR5aag-LRLeSrV4vmssqpekTiQ_ng,5929
244
+ django_unfold-0.51.0.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
245
+ django_unfold-0.51.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.0.1
2
+ Generator: poetry-core 2.1.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
unfold/admin.py CHANGED
@@ -20,6 +20,7 @@ from unfold.forms import ActionForm
20
20
  from unfold.mixins import ActionModelAdminMixin, BaseModelAdminMixin
21
21
  from unfold.overrides import FORMFIELD_OVERRIDES_INLINE
22
22
  from unfold.typing import FieldsetsType
23
+ from unfold.views import ChangeList
23
24
  from unfold.widgets import UnfoldBooleanWidget
24
25
 
25
26
  checkbox = UnfoldBooleanWidget(
@@ -168,6 +169,9 @@ class ModelAdmin(BaseModelAdminMixin, ActionModelAdminMixin, BaseModelAdmin):
168
169
  return redirect(request.GET["next"])
169
170
  return res
170
171
 
172
+ def get_changelist(self, request, **kwargs):
173
+ return ChangeList
174
+
171
175
 
172
176
  class TabularInline(BaseModelAdminMixin, BaseTabularInline):
173
177
  formfield_overrides = FORMFIELD_OVERRIDES_INLINE
@@ -83,6 +83,7 @@ class RelatedDropdownFilter(ValueMixin, DropdownMixin, admin.RelatedFieldListFil
83
83
  ) -> None:
84
84
  super().__init__(field, request, params, model, model_admin, field_path)
85
85
  self.model_admin = model_admin
86
+ self.request = request
86
87
 
87
88
  def choices(self, changelist: ChangeList) -> Generator[dict[str, Any], None, None]:
88
89
  yield {
@@ -4,10 +4,12 @@ from typing import Any, Optional
4
4
  from django.contrib.admin.views.main import ChangeList
5
5
  from django.core.validators import EMPTY_VALUES
6
6
  from django.db.models import QuerySet
7
+ from django.db.models.fields import BLANK_CHOICE_DASH, Field
7
8
  from django.forms import ValidationError
8
9
  from django.http import HttpRequest
9
10
  from django.utils.translation import gettext_lazy as _
10
11
 
12
+ from unfold.admin import ModelAdmin
11
13
  from unfold.contrib.filters.forms import (
12
14
  AutocompleteDropdownForm,
13
15
  DropdownForm,
@@ -123,11 +125,15 @@ class RangeNumericMixin:
123
125
 
124
126
 
125
127
  class AutocompleteMixin:
126
- def __init__(self, *args, **kwargs) -> None:
127
- super().__init__(*args, **kwargs)
128
+ def has_output(self) -> bool:
129
+ return True
128
130
 
129
- if "request" in kwargs:
130
- self.request = kwargs["request"]
131
+ def field_choices(
132
+ self, field: Field, request: HttpRequest, model_admin: ModelAdmin
133
+ ) -> list[tuple[str, str]]:
134
+ return [
135
+ ("", BLANK_CHOICE_DASH),
136
+ ]
131
137
 
132
138
  def choices(
133
139
  self, changelist: ChangeList
@@ -52,7 +52,7 @@ class AutocompleteDropdownForm(forms.Form):
52
52
  self.fields[name] = self.field(
53
53
  label=label,
54
54
  required=False,
55
- queryset=field.remote_field.model.objects.all(),
55
+ queryset=field.remote_field.model.objects,
56
56
  widget=self.widget(field, model_admin.admin_site),
57
57
  )
58
58
 
@@ -61,7 +61,7 @@ class AutocompleteDropdownForm(forms.Form):
61
61
  "admin/js/vendor/jquery/jquery.js",
62
62
  "admin/js/vendor/select2/select2.full.js",
63
63
  "admin/js/jquery.init.js",
64
- "admin/js/autocomplete.js",
64
+ "unfold/js/select2.init.js",
65
65
  )
66
66
  css = {
67
67
  "screen": (
unfold/dataclasses.py CHANGED
@@ -1,6 +1,8 @@
1
1
  from dataclasses import dataclass
2
2
  from typing import Callable, Optional, Union
3
3
 
4
+ from unfold.enums import ActionVariant
5
+
4
6
  from .typing import ActionFunction
5
7
 
6
8
 
@@ -13,6 +15,7 @@ class UnfoldAction:
13
15
  attrs: Optional[dict] = None
14
16
  object_id: Optional[Union[int, str]] = None
15
17
  icon: Optional[str] = None
18
+ variant: Optional[ActionVariant] = ActionVariant.DEFAULT
16
19
 
17
20
 
18
21
  @dataclass
unfold/decorators.py CHANGED
@@ -7,6 +7,8 @@ from django.db.models import Model
7
7
  from django.db.models.expressions import BaseExpression, Combinable
8
8
  from django.http import HttpRequest, HttpResponse
9
9
 
10
+ from unfold.enums import ActionVariant
11
+
10
12
  from .typing import ActionFunction
11
13
 
12
14
 
@@ -18,6 +20,7 @@ def action(
18
20
  url_path: Optional[str] = None,
19
21
  attrs: Optional[dict[str, Any]] = None,
20
22
  icon: Optional[str] = None,
23
+ variant: Optional[ActionVariant] = ActionVariant.DEFAULT,
21
24
  ) -> ActionFunction:
22
25
  def decorator(func: Callable) -> ActionFunction:
23
26
  def inner(
@@ -59,6 +62,11 @@ def action(
59
62
  if icon is not None:
60
63
  inner.icon = icon
61
64
 
65
+ if variant is not None:
66
+ inner.variant = variant
67
+ else:
68
+ inner.variant = ActionVariant.DEFAULT
69
+
62
70
  inner.attrs = attrs or {}
63
71
  return inner
64
72
 
unfold/enums.py ADDED
@@ -0,0 +1,10 @@
1
+ from enum import Enum
2
+
3
+
4
+ class ActionVariant(Enum):
5
+ DEFAULT = "default"
6
+ PRIMARY = "primary"
7
+ SUCCESS = "success"
8
+ INFO = "info"
9
+ WARNING = "warning"
10
+ DANGER = "danger"
@@ -7,6 +7,7 @@ from django.template.response import TemplateResponse
7
7
  from django.urls import reverse
8
8
 
9
9
  from unfold.dataclasses import UnfoldAction
10
+ from unfold.enums import ActionVariant
10
11
  from unfold.exceptions import UnfoldException
11
12
 
12
13
 
@@ -119,6 +120,7 @@ class ActionModelAdminMixin:
119
120
  path=getattr(method, "url_path", action),
120
121
  attrs=method.attrs if hasattr(method, "attrs") else None,
121
122
  icon=method.icon if hasattr(method, "icon") else None,
123
+ variant=method.variant if hasattr(method, "variant") else None,
122
124
  )
123
125
 
124
126
  def get_actions_list(self, request: HttpRequest) -> list[UnfoldAction]:
@@ -265,6 +267,7 @@ class ActionModelAdminMixin:
265
267
  return {
266
268
  "title": action.description,
267
269
  "icon": action.icon,
270
+ "variant": action.variant,
268
271
  "attrs": action.method.attrs,
269
272
  "path": get_action_path(action),
270
273
  }
@@ -276,6 +279,7 @@ class ActionModelAdminMixin:
276
279
  dropdown = {
277
280
  "title": nav_item["title"],
278
281
  "icon": nav_item.get("icon"),
282
+ "variant": nav_item.get("variant", ActionVariant.DEFAULT),
279
283
  "items": [],
280
284
  }
281
285
 
unfold/sections.py ADDED
@@ -0,0 +1,82 @@
1
+ from django.contrib.admin.utils import label_for_field, lookup_field
2
+ from django.db.models import Model
3
+ from django.http import HttpRequest
4
+ from django.template.loader import render_to_string
5
+
6
+ from unfold.utils import display_for_field
7
+
8
+
9
+ class BaseSection:
10
+ def __init__(self, request: HttpRequest, instance: Model) -> None:
11
+ self.request = request
12
+ self.instance = instance
13
+
14
+ def render(self) -> str:
15
+ raise NotImplementedError(
16
+ "Section subclasses must implement the render method."
17
+ )
18
+
19
+
20
+ class TableSection(BaseSection):
21
+ fields = []
22
+ related_name = None
23
+ verbose_name = None
24
+ height = None
25
+
26
+ def render(self) -> str:
27
+ results = getattr(self.instance, self.related_name)
28
+ headers = []
29
+ rows = []
30
+
31
+ for field_name in self.fields:
32
+ if hasattr(self, field_name):
33
+ if hasattr(getattr(self, field_name), "short_description"):
34
+ headers.append(getattr(self, field_name).short_description)
35
+ else:
36
+ headers.append(field_name)
37
+ else:
38
+ headers.append(label_for_field(field_name, results.model))
39
+
40
+ for result in results.all():
41
+ row = []
42
+
43
+ for field_name in self.fields:
44
+ if hasattr(self, field_name):
45
+ row.append(getattr(self, field_name)(result))
46
+ else:
47
+ field, attr, value = lookup_field(field_name, result)
48
+ row.append(display_for_field(value, field, "-"))
49
+
50
+ rows.append(row)
51
+
52
+ context = {
53
+ "request": self.request,
54
+ "table": {
55
+ "headers": headers,
56
+ "rows": rows,
57
+ },
58
+ }
59
+
60
+ if hasattr(self, "verbose_name") and self.verbose_name:
61
+ context["title"] = self.verbose_name
62
+
63
+ if hasattr(self, "height") and self.height:
64
+ context["height"] = self.height
65
+
66
+ return render_to_string(
67
+ "unfold/components/table.html",
68
+ context=context,
69
+ )
70
+
71
+
72
+ class TemplateSection(BaseSection):
73
+ template_name = None
74
+
75
+ def render(self) -> str:
76
+ return render_to_string(
77
+ self.template_name,
78
+ context={
79
+ "request": self.request,
80
+ "instance": self.instance,
81
+ },
82
+ )
unfold/settings.py CHANGED
@@ -54,6 +54,7 @@ CONFIG_DEFAULTS = {
54
54
  },
55
55
  "DASHBOARD_CALLBACK": None,
56
56
  "ENVIRONMENT": None,
57
+ "ENVIRONMENT_TITLE_PREFIX": None,
57
58
  "STYLES": [],
58
59
  "SCRIPTS": [],
59
60
  "SIDEBAR": {
unfold/sites.py CHANGED
@@ -88,6 +88,9 @@ class UnfoldAdminSite(AdminSite):
88
88
  "border_radius": self._get_config("BORDER_RADIUS", request),
89
89
  "colors": self._get_colors("COLORS", request),
90
90
  "environment": self._get_config("ENVIRONMENT", request),
91
+ "environment_title_prefix": self._get_config(
92
+ "ENVIRONMENT_TITLE_PREFIX", request
93
+ ),
91
94
  "tab_list": self.get_tabs_list(request),
92
95
  "styles": self._get_list("STYLES", request),
93
96
  "scripts": self._get_list("SCRIPTS", request),
@@ -225,11 +225,24 @@
225
225
  }
226
226
  };
227
227
 
228
- $this.each(function (i) {
229
- $(this)
230
- .not("." + options.emptyCssClass)
231
- .addClass(options.formCssClass);
232
- });
228
+ // !CHANGED from original. Business logic for tabular inlines is different.
229
+ if ($this.parent().is("tbody")) {
230
+ $this
231
+ .parent()
232
+ .parent()
233
+ .find("tr.form-row")
234
+ .each(function (i) {
235
+ $(this)
236
+ .not("." + options.emptyCssClass)
237
+ .addClass(options.formCssClass);
238
+ });
239
+ } else {
240
+ $this.each(function (i) {
241
+ $(this)
242
+ .not("." + options.emptyCssClass)
243
+ .addClass(options.formCssClass);
244
+ });
245
+ }
233
246
 
234
247
  // Create the delete buttons for all unsaved inlines:
235
248
  $this