django-unfold 0.53.0__py3-none-any.whl → 0.55.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 (56) hide show
  1. {django_unfold-0.53.0.dist-info → django_unfold-0.55.0.dist-info}/METADATA +24 -11
  2. {django_unfold-0.53.0.dist-info → django_unfold-0.55.0.dist-info}/RECORD +56 -33
  3. {django_unfold-0.53.0.dist-info → django_unfold-0.55.0.dist-info}/WHEEL +1 -1
  4. unfold/contrib/filters/admin/__init__.py +17 -0
  5. unfold/contrib/filters/admin/choice_filters.py +173 -0
  6. unfold/contrib/filters/admin/dropdown_filters.py +15 -1
  7. unfold/contrib/filters/admin/mixins.py +25 -0
  8. unfold/contrib/filters/forms.py +41 -3
  9. unfold/contrib/filters/templates/unfold/filters/filters_date_range.html +1 -1
  10. unfold/contrib/filters/templates/unfold/filters/filters_datetime_range.html +1 -1
  11. unfold/layout.py +23 -0
  12. unfold/sites.py +17 -6
  13. unfold/static/admin/js/inlines.js +23 -3
  14. unfold/static/unfold/css/styles.css +1 -1
  15. unfold/static/unfold/fonts/material-symbols/LICENSE +202 -0
  16. unfold/static/unfold/fonts/material-symbols/Material-Symbols-Outlined.woff2 +0 -0
  17. unfold/static/unfold/js/alpine.js +2 -2
  18. unfold/static/unfold/js/select2.init.js +4 -0
  19. unfold/styles.css +2 -1
  20. unfold/templates/admin/change_list.html +15 -13
  21. unfold/templates/admin/change_list_results.html +1 -1
  22. unfold/templates/admin/edit_inline/tabular.html +1 -2
  23. unfold/templates/unfold/components/button.html +1 -1
  24. unfold/templates/unfold/components/chart/cohort.html +2 -2
  25. unfold/templates/unfold/helpers/change_list_filter.html +2 -2
  26. unfold/templates/unfold/helpers/change_list_filter_actions.html +28 -26
  27. unfold/templates/unfold/helpers/edit_inline/tabular_field.html +10 -8
  28. unfold/templates/unfold/helpers/field.html +4 -2
  29. unfold/templates/unfold/helpers/form_label.html +1 -1
  30. unfold/templates/unfold/helpers/tab_action.html +17 -2
  31. unfold/templates/unfold/widgets/clearable_file_input.html +1 -1
  32. unfold/templates/unfold/widgets/clearable_file_input_small.html +1 -1
  33. unfold/templates/unfold/widgets/radio_option.html +1 -1
  34. unfold/templates/unfold_crispy/display_form.html +9 -0
  35. unfold/templates/unfold_crispy/errors.html +3 -0
  36. unfold/templates/unfold_crispy/field.html +23 -0
  37. unfold/templates/unfold_crispy/inputs.html +7 -0
  38. unfold/templates/unfold_crispy/layout/attrs.html +1 -0
  39. unfold/templates/unfold_crispy/layout/baseinput.html +9 -0
  40. unfold/templates/unfold_crispy/layout/button.html +1 -0
  41. unfold/templates/unfold_crispy/layout/buttonholder.html +3 -0
  42. unfold/templates/unfold_crispy/layout/checkbox.html +19 -0
  43. unfold/templates/unfold_crispy/layout/column.html +3 -0
  44. unfold/templates/unfold_crispy/layout/div.html +4 -0
  45. unfold/templates/unfold_crispy/layout/field_errors.html +7 -0
  46. unfold/templates/unfold_crispy/layout/fieldset.html +9 -0
  47. unfold/templates/unfold_crispy/layout/help_text.html +5 -0
  48. unfold/templates/unfold_crispy/layout/help_text_and_errors.html +3 -0
  49. unfold/templates/unfold_crispy/layout/radio_checkbox_select.html +21 -0
  50. unfold/templates/unfold_crispy/layout/row.html +3 -0
  51. unfold/templates/unfold_crispy/layout/table_inline_formset.html +100 -0
  52. unfold/templates/unfold_crispy/uni_form.html +11 -0
  53. unfold/templates/unfold_crispy/whole_uni_form.html +14 -0
  54. unfold/templatetags/unfold.py +26 -14
  55. unfold/widgets.py +88 -1
  56. {django_unfold-0.53.0.dist-info → django_unfold-0.55.0.dist-info}/LICENSE.md +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: django-unfold
3
- Version: 0.53.0
3
+ Version: 0.55.0
4
4
  Summary: Modern Django admin theme for seamless interface development
5
5
  License: MIT
6
6
  Keywords: django,admin,tailwind,theme
@@ -27,6 +27,7 @@ Description-Content-Type: text/markdown
27
27
  ## Unfold Django Admin Theme
28
28
 
29
29
  [![PyPI - Version](https://img.shields.io/pypi/v/django-unfold.svg?style=for-the-badge)](https://pypi.org/project/django-unfold/)
30
+ [![Discord](https://img.shields.io/discord/1297493955231088650?style=for-the-badge&logo=discord&logoColor=%23ffffff&color=7289da)](https://discord.gg/9sQj9MEbNz)
30
31
  [![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
32
  ![Pre Commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white&style=for-the-badge)
32
33
  ![Code Style - Ruff](https://img.shields.io/badge/code%20style-ruff-30173D.svg?style=for-the-badge)
@@ -43,26 +44,31 @@ Transform your Django admin into a powerful, modern administrative interface wit
43
44
 
44
45
  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
 
47
+ ## Unfold Studio
48
+
49
+ Unfold Studio is a theme customizer for Django admin that helps you create a branded interface. You can customize colors, upload your logo, and adjust the style without coding. The tool is currently in development, and [you can join the waitlist](https://unfoldadmin.com/studio/) to be notified when it's available.
50
+
46
51
  ## Fresh Features & Enhancements
47
52
 
48
- - **Autocomplete filters:** Enhance filter functionality with built-in autocomplete support
53
+ - **Conditional fields:** Show or hide fields dynamically based on the values of other fields in the form
54
+ - **Infinite paginator:** Efficiently handle large datasets with seamless pagination that reduces server load
55
+ - **Checkbox & radio filters:** Enhanced filter options with checkbox and radio interfaces for intuitive filtering
49
56
  - **Site dropdown:** Configurable dropdown menu in the header area for managing custom navigation links
50
57
  - **Dropdown actions:** Organize action items in customizable dropdown menus
51
- - **Custom tab navigation:** Create flexible, structured tab navigation with customizable routing
52
-
53
58
 
54
59
  ## Core Features & Capabilities
55
60
 
56
61
  - **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.
62
+ - **Sidebar navigation**: Simplifies the creation of sidebar menus with icons, collapsible sections, and more.
63
+ - **Dark mode support**: Includes both light and dark mode themes.
64
+ - **Flexible actions**: Provides multiple ways to define actions throughout the admin interface.
65
+ - **Advanced filters**: Features custom dropdowns, autocomplete, numeric, datetime, and text field filters.
66
+ - **Dashboard tools**: Includes helpers for building custom dashboard pages.
67
+ - **UI components**: Offers reusable interface components such as cards, buttons, and charts.
68
+ - **WYSIWYG editor**: Built-in support for WYSIWYG editing through Trix.
64
69
  - **Array widget:** Built-in widget for `django.contrib.postgres.fields.ArrayField`
65
70
  - **Inline tabs:** Group inlines into tab navigation in the change form
71
+ - **Conditional fields:** Show or hide fields dynamically based on the values of other fields in the form
66
72
  - **Model tabs:** Allow defining custom tab navigation for models
67
73
  - **Fieldset tabs:** Merge multiple fieldsets into tabs in the change form
68
74
  - **Sortable inlines:** Allow sorting inlines by dragging and dropping
@@ -73,9 +79,16 @@ Need assistance with implementing Unfold or require custom Django development? P
73
79
  - **Font colors:** Adjust font colors for better readability
74
80
  - **Changeform modes:** Display fields in compressed mode in the change form
75
81
  - **Language switcher:** Allow changing language directly from the admin area
82
+ - **Infinite paginator:** Efficiently handle large datasets with seamless pagination that reduces server load
76
83
  - **Parallel admin:** Supports [running the default admin](https://unfoldadmin.com/blog/migrating-django-admin-unfold/?utm_medium=github&utm_source=unfold) alongside Unfold.
77
84
  - **Third-party packages:** Provides default support for multiple popular applications.
78
85
  - **Configuration:** Allows basic options to be changed in `settings.py`.
79
86
  - **Dependencies:** Built entirely on `django.contrib.admin`.
80
87
  - **VS Code:** Project configuration and development container included.
81
88
 
89
+ ## Credits
90
+
91
+ - Icons: [Material Symbols](https://github.com/google/material-design-icons)
92
+ - Font: [Inter](https://github.com/rsms/inter)
93
+ - Charts: [Chart.js](https://github.com/chartjs/Chart.js)
94
+
@@ -5,22 +5,23 @@ unfold/checks.py,sha256=8I3i4xR_KgyJdpQyZUZzKNeyYf-sNzg6PAlsREuMfgI,1664
5
5
  unfold/components.py,sha256=vqkQzseYUvLXDohmTVAlbKopALjyX4WA9yglvdfhqu4,1283
6
6
  unfold/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  unfold/contrib/filters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- unfold/contrib/filters/admin/__init__.py,sha256=2pyv21jMqQVC8pnP8FOERHRH2hgZSOLQzV0BUn5wjHo,1216
8
+ unfold/contrib/filters/admin/__init__.py,sha256=7pooAoA2Y9MbBL_RTJBZeIAwV5ECrOvMbe0_egoHfew,1663
9
9
  unfold/contrib/filters/admin/autocomplete_filters.py,sha256=Jh3m3iQ8YubZRQDVzHPGfpk9RulOhHkZc0N7L6KV9wc,514
10
+ unfold/contrib/filters/admin/choice_filters.py,sha256=xptxmUM9FL4xZklBOBnFR0yNlzNAZgEt3xLBtMBgQko,5575
10
11
  unfold/contrib/filters/admin/datetime_filters.py,sha256=cVari_7jsfeYxJoRBhcAUOr6v9XdtDtMuMs-S1Irafo,7757
11
- unfold/contrib/filters/admin/dropdown_filters.py,sha256=aZhBTEjtbeaOdYZK4nYRmA38usy9rhVTM4L_08MGU0I,3360
12
- unfold/contrib/filters/admin/mixins.py,sha256=iOO89KpVmKig_4RPJem2TqIwZO-ROUjGTmoDmBkgyLk,4945
12
+ unfold/contrib/filters/admin/dropdown_filters.py,sha256=aBJeutavLRocbrverAUM6mx4_kCyDWKnjcx3JRVqXuc,3837
13
+ unfold/contrib/filters/admin/mixins.py,sha256=4SiJ1Qnp-REUXOhk80zq8uW0nc2i-r8aftvSaFrpPXw,5820
13
14
  unfold/contrib/filters/admin/numeric_filters.py,sha256=8GNmesgMmMIfEZb2IrGbaBoJuvB2FpIc7wPIPBpHat4,6420
14
15
  unfold/contrib/filters/admin/text_filters.py,sha256=19cOEGpSaXafcM8QuGiYaWmNi5UIQnCXEhKG-vCTfe8,2088
15
16
  unfold/contrib/filters/apps.py,sha256=wEySJy0gMLzFLb9XNKE-RexiO05X7NaQ5QmxZyziJ_k,136
16
- unfold/contrib/filters/forms.py,sha256=_eHiUaTKltkZ3pWG77LiWYnEVMC-2A-wj1LMLkcCPvc,7233
17
+ unfold/contrib/filters/forms.py,sha256=8p1JKYSqzB-GkUQloy-CM3aprhtTgJhI05aCG-qSdkw,8069
17
18
  unfold/contrib/filters/static/unfold/filters/css/nouislider.min.css,sha256=rddL_jOGGVEY6wR-aw0VYovAfz5fPeAIsulrlSNb1hc,4221
18
19
  unfold/contrib/filters/static/unfold/filters/js/DateTimeShortcuts.js,sha256=jgFNBDf6aHvUlyv0LEDHggXO-xA8pWOCWFWcVupdA30,19332
19
20
  unfold/contrib/filters/static/unfold/filters/js/admin-numeric-filter.js,sha256=nTkiiJk4Abn9d6KigxPSEsereFhFq-v5n_boiiY1eII,1668
20
21
  unfold/contrib/filters/static/unfold/filters/js/nouislider.min.js,sha256=aIEt5UlLNnEv4-HPyxcLqu9dTS7gXiMm35Mm0rFmQ0Q,26683
21
22
  unfold/contrib/filters/static/unfold/filters/js/wNumb.min.js,sha256=gayD3el5iizhy0DlsyKfZvfOfOZHDmb7BPvOcT97GSg,2236
22
- unfold/contrib/filters/templates/unfold/filters/filters_date_range.html,sha256=9wVy7LX-9b9lXY53pSC5bCts2yv82EDHP5BL1PczM_k,673
23
- unfold/contrib/filters/templates/unfold/filters/filters_datetime_range.html,sha256=9wVy7LX-9b9lXY53pSC5bCts2yv82EDHP5BL1PczM_k,673
23
+ unfold/contrib/filters/templates/unfold/filters/filters_date_range.html,sha256=PeY1O1YiqjFHt4iExWTf1084uHS6bLVHFWe_reCigqk,673
24
+ unfold/contrib/filters/templates/unfold/filters/filters_datetime_range.html,sha256=PeY1O1YiqjFHt4iExWTf1084uHS6bLVHFWe_reCigqk,673
24
25
  unfold/contrib/filters/templates/unfold/filters/filters_field.html,sha256=UTlSZlpg-gAc_a-EJLLF0NI_ofuSHQ2kMMoAs99nL2E,164
25
26
  unfold/contrib/filters/templates/unfold/filters/filters_numeric_range.html,sha256=aHggmpsmwts78x-BfAApHkfOImg8NEMi1FEJZwTqveI,651
26
27
  unfold/contrib/filters/templates/unfold/filters/filters_numeric_single.html,sha256=fWupjTY6kInxOsm2-eEMIB3IZoslnLJmxBdOdMxO-Is,588
@@ -77,6 +78,7 @@ unfold/enums.py,sha256=9sTfyEycMWeoGPBa-ft6ZhQGnW1vkFg108RMBVf9nko,187
77
78
  unfold/exceptions.py,sha256=gcCj1ox61E137bk_0Cqy4YC3SttdPgB-fiJUqpmyHSE,43
78
79
  unfold/fields.py,sha256=J3goIMlP_XOmQ85Xgh2v5MylXSP1o5I7o9_So2FQn2k,7461
79
80
  unfold/forms.py,sha256=3MrVG9jDdDsrJHph-cimZXRycfdoAw-KhT0uJJInG7E,4552
81
+ unfold/layout.py,sha256=idG4v0AumFPyy16KUlKtWrs9kyBQIKY_Ln26Lx9DOPg,501
80
82
  unfold/mixins/__init__.py,sha256=YlhoDs9Y_DXQ8Ejr3enxuHMS1-Ij9fwukxNwpeOS4Co,190
81
83
  unfold/mixins/action_model_admin.py,sha256=BPajuTGf7zAaZOqIq4shX8VQ3NTxWQpedvG58fmCTjk,12036
82
84
  unfold/mixins/base_model_admin.py,sha256=PR4eqU48yB4CNy9Bjd7fjxbOFiFpZM4etYmBOSaRX_M,4140
@@ -84,29 +86,30 @@ unfold/overrides.py,sha256=ERVY9boZiXgjDYcTEZcIp7KWoeBZ45VM_zN31yAOjyQ,2922
84
86
  unfold/paginator.py,sha256=vWCIfpuWbV3nvIkQOPyD7MLTg2hZplHz3rze42d-qiA,268
85
87
  unfold/sections.py,sha256=Lcg3xCZ76fqjm4vD4x7YdE5VsbTKluL-sX5QTEBlHxA,2379
86
88
  unfold/settings.py,sha256=3ICha2I0oSaHhajG8159nHdNTYJInBtRQq9VziWKYKs,2709
87
- unfold/sites.py,sha256=fx3U0kIfN3My4UNiXO_ggrudmFvYNglMAIARaMa2gqY,16321
89
+ unfold/sites.py,sha256=n1IY7xS4316ZfjcwKWQlnkPtzdVCifbltBT-yZoUu3k,16657
88
90
  unfold/static/admin/js/admin/RelatedObjectLookups.js,sha256=alI0-yq7YPDJJJn-yg1ce79-Cv88yQDUrfaGqFZnsaY,9048
89
- unfold/static/admin/js/inlines.js,sha256=74QODSKEkpKse4bft4wIFZquROcr2-hVTt9CEWOIJak,15061
91
+ unfold/static/admin/js/inlines.js,sha256=zcYwLGI_6RHg-gucDbbhp43RRoZd3so8bPk841KFaIE,15573
90
92
  unfold/static/unfold/css/simplebar.css,sha256=5LLaEM11pKi6JFCOLt4XKuZxTpT9rpdq_tNlaQytFlU,4647
91
- unfold/static/unfold/css/styles.css,sha256=DupCEMUvhh3SW1rpPpT06j-M9bm4v9TYfasw0_-uf68,160274
93
+ unfold/static/unfold/css/styles.css,sha256=LolJmXEJUWR42aC7fNQLhfoQZBSzTE9vD-1bynfFeGo,162977
92
94
  unfold/static/unfold/fonts/inter/Inter-Bold.woff2,sha256=-oiBJ7baAVtlVp8DUfO1w5GtkokElR8cIOn4RiqNleo,114840
93
95
  unfold/static/unfold/fonts/inter/Inter-Medium.woff2,sha256=D_PpRhThST61VjFP0keubEqFp3g7TMhr5TmUDPg_Kkg,114348
94
96
  unfold/static/unfold/fonts/inter/Inter-Regular.woff2,sha256=4G9rG8VTqupORmgCPtCrChRxKcMQf1Ebx9A9NhsK4IU,111268
95
97
  unfold/static/unfold/fonts/inter/Inter-SemiBold.woff2,sha256=XLcQPk5gWYmv68A9mJx5IB5UshtRg9szmB9w25F4owE,114812
96
98
  unfold/static/unfold/fonts/inter/styles.css,sha256=QqdgevXVfcD6vZGo8ciSkaEG_62_YcZg0hvHTNgJ56E,608
97
- unfold/static/unfold/fonts/material-symbols/Material-Symbols-Outlined.woff2,sha256=V6mmjk69Ee-coQvMsGV0tcNgV3E1nb7N9IKW8HVUBzk,256424
99
+ unfold/static/unfold/fonts/material-symbols/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
100
+ unfold/static/unfold/fonts/material-symbols/Material-Symbols-Outlined.woff2,sha256=sMDmadC_mJOI200LuWcwAZRwAqDWLgdj85JA0x42qu8,274228
98
101
  unfold/static/unfold/fonts/material-symbols/styles.css,sha256=ZX1icA_BXCVL0eoY2H6XR8VT_Fxl_KnV6vFBm_OImHA,535
99
102
  unfold/static/unfold/js/alpine.anchor.js,sha256=2Jg9aUq749pjFynzr_H1NK3lf-nXrbHMtO9wvlWJyIQ,15524
100
- unfold/static/unfold/js/alpine.js,sha256=NY2a-7GrW--i9IBhowd25bzXcH9BCmBrqYX5i8OxwDQ,44659
103
+ unfold/static/unfold/js/alpine.js,sha256=PtHu0lJIiSHfZeNj1nFd6wTX-Squ255SGZ_fc8seCtM,44758
101
104
  unfold/static/unfold/js/alpine.persist.js,sha256=jFBwr6faTqqhp3sVi4_VTxJ0FpaF9YGZN1ZGLl_5QYM,837
102
105
  unfold/static/unfold/js/alpine.resize.js,sha256=mXR2L6neT584cfNLY5_imDq5DKjW1noXys7fhb1yxY4,703
103
106
  unfold/static/unfold/js/alpine.sort.js,sha256=q6LxgConwu8M8R03mZSBcsKwJv6fF7oomP8sqLxVQ0w,37891
104
107
  unfold/static/unfold/js/app.js,sha256=mxCSV8gZvRLHab-_Xm_229NtQ9IX-59vS_GKWTp9liM,7748
105
108
  unfold/static/unfold/js/chart.js,sha256=22W6cFERR-CElMOKRgMMicueMVP0Vf7FBEBYH8Z8tCk,200633
106
109
  unfold/static/unfold/js/htmx.js,sha256=acrv0NqSJpBm5yXX_hdeJrnVDJYuMFZFnAxHcVTNudM,50918
107
- unfold/static/unfold/js/select2.init.js,sha256=gXZngZh-l5ID2-VmndpGseNi6A0zKB18UgPyCor68CU,1040
110
+ unfold/static/unfold/js/select2.init.js,sha256=l0O8ggw_CkAw-QtH3qEzC8xWk0mR9QHjy4VzAjMwiQQ,1109
108
111
  unfold/static/unfold/js/simplebar.js,sha256=t-uG1FAD6ZoiMeN--wac0XRS7SxoDVG6zvRnGuEp7X8,27176
109
- unfold/styles.css,sha256=6lYnrPCD8anvFHGN9DZJFsW8iDn7T3qvP-i8zNWulpo,19112
112
+ unfold/styles.css,sha256=Mbe0mO2608aH3bCVllxTKb6OcsMIy-ZAugcwaWBwM0E,19142
110
113
  unfold/templates/admin/actions.html,sha256=aroIid16mORcx-0p8O2dOoWupEoTGX66pt-PAXjSYZ0,3063
111
114
  unfold/templates/admin/app_index.html,sha256=GSBry97gDcK3scTP-Fs4FXcSItRxxE87Wv4sDtMTlbc,1244
112
115
  unfold/templates/admin/app_list.html,sha256=VtntgHpbZdXbt_HXBLAtbuMdz1alS7F_S7eG37M5Rig,2855
@@ -116,14 +119,14 @@ unfold/templates/admin/base.html,sha256=3xQmoD_7cu2UlgEdvnt7v_CibT9t1Iul0b-VU2Aw
116
119
  unfold/templates/admin/base_site.html,sha256=UOsecaCycpyn_ygJNIKO7MQtDFJuHv--r83-mzaVY30,300
117
120
  unfold/templates/admin/change_form.html,sha256=ZVOtRNTppyhWddRs3qdyWIznWXRl6QGsIzDO8-C-Puk,5665
118
121
  unfold/templates/admin/change_form_object_tools.html,sha256=eyeH-i2HgEM0Yi-OJA2D1VnKJyC19A_my1IDGxxoP8Y,593
119
- unfold/templates/admin/change_list.html,sha256=AhGUdt-S3m30WhSraWnBdLwZQ1JU9yZeVDL0WDqCEMI,5164
122
+ unfold/templates/admin/change_list.html,sha256=o3nPQUHo9rCpaNfoGfBl1owhIDvk_gwSESbCP0bK_YQ,5291
120
123
  unfold/templates/admin/change_list_object_tools.html,sha256=cmMiT2nT20Ph5yfpj9aHPr76Z-JP4aSXp0o-Rnad28s,147
121
- unfold/templates/admin/change_list_results.html,sha256=n64K5ocS62kujxzzkojzOx4jJuiYcO8r4mcJfcsCQAs,7931
124
+ unfold/templates/admin/change_list_results.html,sha256=H7JtxfZSRIwYQTYdBAumFpkATETSE2rvNgwCsUSGzno,7931
122
125
  unfold/templates/admin/date_hierarchy.html,sha256=Jl_Vk05fXvsSvod5Dw2p3KhpCQGjtSX1zqlNjjkBFR4,1411
123
126
  unfold/templates/admin/delete_confirmation.html,sha256=yT_NHbFHZEjkSCaGVcM52GCG-FDmWiJdTFLbq9CBCx4,4619
124
127
  unfold/templates/admin/delete_selected_confirmation.html,sha256=QR0JhrPR8YI8KpQnB3xyrKxaui-_pEQmfaMDbcXjjZ0,4391
125
128
  unfold/templates/admin/edit_inline/stacked.html,sha256=-ASy7Jd0SwWBDxurucbus86YT2AokJEcCUrqPlHVDQA,7644
126
- unfold/templates/admin/edit_inline/tabular.html,sha256=FBgzUb-U0cZCN28-cpHzRSyPE6bgseD_r3MY1AP0nGQ,2813
129
+ unfold/templates/admin/edit_inline/tabular.html,sha256=GFXgOwMK0WZfFtMdfw7JMAXTUmW7cavEh9FYQ2dTgh4,2893
127
130
  unfold/templates/admin/filter.html,sha256=0B_hpLybHw1wUPPCN3KJvoWrx03iFeqP8m1LRCjnLlQ,2012
128
131
  unfold/templates/admin/includes/fieldset.html,sha256=gX-dc-jPLswk21XSKUXzAU8WFl3CFfeVrIAU2bviPyg,812
129
132
  unfold/templates/admin/includes/object_delete_summary.html,sha256=FgwfapZCKWtnFtTHqh1MRuxxLot4bAw92WCcR_V8ImI,444
@@ -138,10 +141,10 @@ unfold/templates/auth/widgets/read_only_password_hash.html,sha256=bQiYKDKJkyVP0_
138
141
  unfold/templates/registration/logged_out.html,sha256=GgLzqmOGpiw5FcA-Aw_T6YvhYHhGFWhyES40T28waLQ,1002
139
142
  unfold/templates/registration/password_change_done.html,sha256=9HDpSraz3Kxdy0Fghbn-Lv0GAtpPgG6cuO7fvfMiYg8,1077
140
143
  unfold/templates/registration/password_change_form.html,sha256=EgakVWzpQUEJKQS0AOfk8O_CY1bKbyWXSUuBaxtQEdU,2232
141
- unfold/templates/unfold/components/button.html,sha256=TABo79ppuGlm2ENvRs6L3Vne8B5_9he_OhZTnPMiitQ,473
144
+ unfold/templates/unfold/components/button.html,sha256=db7bT5aR4WXE3aJzHpKkRPGCD2UHrNgVRvZXLSHmIC4,603
142
145
  unfold/templates/unfold/components/card.html,sha256=FVLN7kQZqMd_uhEi1LpiN9FUxZCa4RgGHYGmofCtQro,1141
143
146
  unfold/templates/unfold/components/chart/bar.html,sha256=nDdDCUXvFd793OpNgNPQo0vBmvYngMsQyPHVTf1vfOw,297
144
- unfold/templates/unfold/components/chart/cohort.html,sha256=elZj9e9E9cfVey_9LSOaDoVSE3Wn3BagSrwIXRSFadM,2354
147
+ unfold/templates/unfold/components/chart/cohort.html,sha256=wDjRb2IT1XEJ--Y1BrSaMOeM7XXy9iohJR_4RZ2ilSs,2362
145
148
  unfold/templates/unfold/components/chart/line.html,sha256=DHaZUFTlCs5cX7ioYdTzoN4ITHWNcEoNSUp7v3hlo_E,298
146
149
  unfold/templates/unfold/components/container.html,sha256=WBk1rGHnTsObi3pJCpL3dfFAUQ2abDmokU0Lee7R9CI,83
147
150
  unfold/templates/unfold/components/flex.html,sha256=_hBsQLJ6-7MfEfXNp5Wy-ykNtPMnnNg_io2IMGegn3s,134
@@ -162,20 +165,20 @@ unfold/templates/unfold/helpers/attrs.html,sha256=Mwpj72kuwYj8hOT3J2T8qx6f1r_4xw
162
165
  unfold/templates/unfold/helpers/boolean.html,sha256=kcSZr3siQeBWIy_jsx1tFf4m6IB3ooRnu8UUNQrh6so,569
163
166
  unfold/templates/unfold/helpers/breadcrumb_item.html,sha256=9T6ojN7LOXIlgwSwlIwHgy5U22eQYtarCqcmzsQIoPU,201
164
167
  unfold/templates/unfold/helpers/change_list_actions.html,sha256=p1_vC2Q_Fb-gAHA8y1zzOXqqn5TPQMrQfE26PkOY_ok,656
165
- unfold/templates/unfold/helpers/change_list_filter.html,sha256=0l-c4H2PcDkAuzI6asAJf2rBfYavYG62F9d7yWWdkSI,1852
166
- unfold/templates/unfold/helpers/change_list_filter_actions.html,sha256=fTlM6jyS83FhGulFYuhFVLJOGHRJV3mFCWDQnp1kp0U,1760
168
+ unfold/templates/unfold/helpers/change_list_filter.html,sha256=oAWtb29vT0g2myp7IqLr_a7O72TboxUskwOEId4ZnpY,1921
169
+ unfold/templates/unfold/helpers/change_list_filter_actions.html,sha256=_D_ub3xh9sJFiM4BbmfdlvZzXb8rXQEwY9yQn6KM2Xc,1973
167
170
  unfold/templates/unfold/helpers/delete_submit_line.html,sha256=N1w_TDIDN7Spj5diuhRUVOVgz2TiSeHVK2QvBjTLv2w,665
168
171
  unfold/templates/unfold/helpers/display_dropdown.html,sha256=e83t_lR2uSxnNoDYKnTKyD57V3FTMCM9T0h0DeFdAV8,2850
169
172
  unfold/templates/unfold/helpers/display_header.html,sha256=rhru2GSxR0mH8_FEQuQVIS8gGGjaiWMV9f2HCPGMsaQ,1698
170
173
  unfold/templates/unfold/helpers/display_label.html,sha256=LS9DWzYjHkYLV27sZDwyXlg2sLJ0AlId9FbjnXpsbfg,317
171
174
  unfold/templates/unfold/helpers/edit_inline/tabular_delete.html,sha256=KFp6d8whXp2DlRyHJF1OsCkJa3Vy-UU-nkQXSlpuui0,928
172
175
  unfold/templates/unfold/helpers/edit_inline/tabular_error.html,sha256=8XGlgUJ47JllmXhwPZDlcl81NzZmvuBIp8FZBWoeu9Q,336
173
- unfold/templates/unfold/helpers/edit_inline/tabular_field.html,sha256=BRCAXdv-HBWyhKK__whswrNiXIH6roexbTKo1w41Btc,919
176
+ unfold/templates/unfold/helpers/edit_inline/tabular_field.html,sha256=JDcSvqozjjNB1wAXcmJCi1xI1iXQAIxylHz4PYTPMkU,1002
174
177
  unfold/templates/unfold/helpers/edit_inline/tabular_heading.html,sha256=ER8R64wnKOu26WTwP4_Wxt-LRB_zRkXLhheZ_utVvKY,1523
175
178
  unfold/templates/unfold/helpers/edit_inline/tabular_row.html,sha256=Cfs2m5eh3mLcMgL0_dSAokAscgq4q19KsnUPZECmDgw,2013
176
179
  unfold/templates/unfold/helpers/edit_inline/tabular_title.html,sha256=JPSue6mD1-KZ3tiymbRrv1G2XgsSim4cT_6HhzYJaYY,2710
177
180
  unfold/templates/unfold/helpers/empty_results.html,sha256=KV9DLKLURDtlkjDI88u05l6cXiOoeSv1nR4wFNIQ2hE,1933
178
- unfold/templates/unfold/helpers/field.html,sha256=Ds-zUHkdyxamfUCVNhxvtM0XoJg9OCA0QcsLbLWv4oo,882
181
+ unfold/templates/unfold/helpers/field.html,sha256=awM8lUlERpPSSz9TczWrMvxXzY8jGbEvix0JzWvHMVE,979
179
182
  unfold/templates/unfold/helpers/field_readonly.html,sha256=4qtXjWE7SA2qZSTYLOv0lT4pQfD0TE34mvWQJY7jhS8,237
180
183
  unfold/templates/unfold/helpers/field_readonly_value.html,sha256=6DNteF8x6_tihQZVCGgz2CqB0ogsLRJhxgDep0sHguc,464
181
184
  unfold/templates/unfold/helpers/fieldset_row.html,sha256=LriorPLXU4VmqstjX1oBc3T49H8CbhCrRxwQ7YfUSkI,1219
@@ -183,7 +186,7 @@ unfold/templates/unfold/helpers/fieldset_row_checkbox.html,sha256=fJh5dZstm8f8pP
183
186
  unfold/templates/unfold/helpers/fieldset_row_field.html,sha256=xXxmELXMXzbNclp36rQn_09Uekq-RQkDP3kRT0Bp6rA,643
184
187
  unfold/templates/unfold/helpers/fieldsets_tabs.html,sha256=KW2rzVqpIICEu55GR_KnuOoXOGnqTZOQAKIuW-u8cAU,1459
185
188
  unfold/templates/unfold/helpers/form_errors.html,sha256=EwerIJptSCWXvtAJ1IZKfEn98qlShBIGavsTThbklAs,266
186
- unfold/templates/unfold/helpers/form_label.html,sha256=BRX3DxVQfEvcmpFcRuhl4v_icMCCd5O_zmYm6MGLtts,327
189
+ unfold/templates/unfold/helpers/form_label.html,sha256=7FfaXfviQmqKpsA1E7NSwM8rJiMNLl9e73XQram0Pfs,249
187
190
  unfold/templates/unfold/helpers/header.html,sha256=ZoQH_Fs1v7fbo6fWQ5UEgfM9xPQlsYQxeabLf7nndB8,1050
188
191
  unfold/templates/unfold/helpers/header_back_button.html,sha256=6DXkxsZJnIt0Z_AILDJNlj1gntEetFD-_b40mWFXwro,413
189
192
  unfold/templates/unfold/helpers/help_text.html,sha256=o-2_hyruIr_Xt0fo38aGgrpptPJFhddnVMPOVQOYhE4,113
@@ -210,7 +213,7 @@ unfold/templates/unfold/helpers/site_dropdown.html,sha256=Zwg5ZGVIEHAI2h-YcWDDBz
210
213
  unfold/templates/unfold/helpers/site_icon.html,sha256=qSEpI1RrNlk6ad6HDiBa74vjsYqGgmEgVbfSXdyyMLI,1485
211
214
  unfold/templates/unfold/helpers/site_logo.html,sha256=S_QJoT2qh0xw0ciaKxoT4GJ6QIH5eqgRSC0abbWWkOI,423
212
215
  unfold/templates/unfold/helpers/submit.html,sha256=4Mgf4lx7Atm8GPqD6LTJK3NA9zoSJjs9VPig7sDp8Ao,203
213
- unfold/templates/unfold/helpers/tab_action.html,sha256=s_nWsB350qtjsn_u3EJpIRfAM7uLc40z1amVel469nw,2261
216
+ unfold/templates/unfold/helpers/tab_action.html,sha256=ODm7ws5sbhpE4OvGuQbzynlVwk6AJRreMUra6hh1lxM,3306
214
217
  unfold/templates/unfold/helpers/tab_actions.html,sha256=DMNqY1YyrNrcutOMC3J1neZZjIkPeYShp1i5xZ10nrc,695
215
218
  unfold/templates/unfold/helpers/tab_items.html,sha256=Gi6cjYJ7tJWO6zSXjg8xNHY9ALpYzjQOEORusf_AZfg,3325
216
219
  unfold/templates/unfold/helpers/tab_list.html,sha256=Tqkug9GyoIQ2geVKWrnnuE0bxeTRXj0MSEwwixoOGz4,436
@@ -221,12 +224,12 @@ unfold/templates/unfold/layouts/base.html,sha256=e9T-vuPvrySHf23LLwRuTQXUg0Q4x-6
221
224
  unfold/templates/unfold/layouts/base_simple.html,sha256=VigjNWnWOt_XtbahvqsroPf8mdwl7cDGbg5fEaLmG9s,1211
222
225
  unfold/templates/unfold/layouts/skeleton.html,sha256=TmZ0hX5j7McwSiYcdGGuhAjDunPDCWtPC7lDF6hbtDk,4641
223
226
  unfold/templates/unfold/templatetags/preserve_changelist_filters.html,sha256=sx2jUhogNY4emBhY8PqxQ6mXifbXQb_IQI9Hd0boJI0,111
224
- unfold/templates/unfold/widgets/clearable_file_input.html,sha256=4vsLRjqOmGqdU4aPSq81rc-mdRvpBr-H_bC5ScyUkEY,2231
225
- unfold/templates/unfold/widgets/clearable_file_input_small.html,sha256=NNlosUwhzv-3SZH9LdliL5c6fdoVNRb1JP0uHwFV-N8,2849
227
+ unfold/templates/unfold/widgets/clearable_file_input.html,sha256=3C4N7OZaiQILNahs12NotNxlQ5QInaXVQtMR4bekHw8,2149
228
+ unfold/templates/unfold/widgets/clearable_file_input_small.html,sha256=FkjdsrkrBa0GxmY3RNZoU08Xs5aDrOD4Q8fU8VbY_vU,2574
226
229
  unfold/templates/unfold/widgets/date.html,sha256=ih9wj8koTaHb9s1NGUmyN9rHvSAmqCMbti9ONDOIujg,122
227
230
  unfold/templates/unfold/widgets/foreign_key_raw_id.html,sha256=7-JPapXS2Ty0MLXNdZ1jCuydqc6JyDs-8-w9b8TcmVU,1075
228
231
  unfold/templates/unfold/widgets/radio.html,sha256=7Mgc92mMwJdVLjCxoGj5lo76KNaN5dKKktV3vzmbeqA,652
229
- unfold/templates/unfold/widgets/radio_option.html,sha256=UVgNUd_DuIHc4tRpnvYnJwG67PycYT2sBAyuVGAY0RM,307
232
+ unfold/templates/unfold/widgets/radio_option.html,sha256=wVg6zIB0O44vwBgQCCphPuCXeh-gaDg6ed-0gcf5kg4,324
230
233
  unfold/templates/unfold/widgets/range.html,sha256=Zhfj2VTusS3nZjOYR7slcjk1JtFK0psZbaSCw6TDY1I,294
231
234
  unfold/templates/unfold/widgets/related_widget_wrapper.html,sha256=4RsFmwlm6De85wsP6W4PvqKosNUPKKNb95RIRh0UUgs,3895
232
235
  unfold/templates/unfold/widgets/split_datetime.html,sha256=2-k9cF1iAeYp3iUT4_9KIIDyZEG3Z25ls34dLan9Z3M,1094
@@ -235,14 +238,34 @@ unfold/templates/unfold/widgets/split_money.html,sha256=AFLUBmzGbY-RXgsfz7gaDxVR
235
238
  unfold/templates/unfold/widgets/textarea.html,sha256=-ZLDGrtASero7L-J3VvTNq_KjPAZh_kLVw0Ow3awqXM,144
236
239
  unfold/templates/unfold/widgets/time.html,sha256=ih9wj8koTaHb9s1NGUmyN9rHvSAmqCMbti9ONDOIujg,122
237
240
  unfold/templates/unfold/widgets/url.html,sha256=IRLgW44VTKN7UrSWeywJwaxQhfG5jhhXuT-KTadKX58,304
241
+ unfold/templates/unfold_crispy/display_form.html,sha256=tGyr8hvMlnKkm2ILbVj0enj6IrjtqiKo6nO9Z-zHE2Q,270
242
+ unfold/templates/unfold_crispy/errors.html,sha256=bzTXuZh_UkQLb4sPaa0En5Uopveoe573TaEOM9OQVcw,132
243
+ unfold/templates/unfold_crispy/field.html,sha256=7Q55yPp0-lkIF2v916GNJbjWjaRlQSvlLJ6KvG9TabI,1610
244
+ unfold/templates/unfold_crispy/inputs.html,sha256=GFOh6U3XzZJvUAZ4_V9Jrbm3FusI5flWzT_sEWLn8tI,294
245
+ unfold/templates/unfold_crispy/layout/attrs.html,sha256=LsLlfKenzHKl6n25m4Ers2NepLSA_RBy9AqezKZ7rH8,173
246
+ unfold/templates/unfold_crispy/layout/baseinput.html,sha256=GjMxXoqpnxCPkPC1E3v_crzlxDb_hHMf_UgJYfqSsYE,440
247
+ unfold/templates/unfold_crispy/layout/button.html,sha256=evlO80en9FkbW3UayLPTNUZXAYvgr3slSAsGPKXs96M,67
248
+ unfold/templates/unfold_crispy/layout/buttonholder.html,sha256=ruHqViROk7nh4luckA8-mcfmnYBqsVM85e8j0rOi3cU,415
249
+ unfold/templates/unfold_crispy/layout/checkbox.html,sha256=DT3zJIUCDuGJ-gxaaNgHUSWfU7oWyk5lvJPREGv830w,732
250
+ unfold/templates/unfold_crispy/layout/column.html,sha256=Bob4xRcbJOHScDjSjLMRIMNf4lonNmm8F_JOm2azTik,172
251
+ unfold/templates/unfold_crispy/layout/div.html,sha256=RE9qQ2w2I2zpi7Z7xzVmVO03UXq0yZvMw-W7rVJkEdw,174
252
+ unfold/templates/unfold_crispy/layout/field_errors.html,sha256=pEn-c6Bfdg54vRm2FxmM8BGbvN0O2R92bnj_gL81X_Q,274
253
+ unfold/templates/unfold_crispy/layout/fieldset.html,sha256=nfIp48NjAJUyNYHkrY7LLEvdgm9rkbytupqzLWTgkFc,581
254
+ unfold/templates/unfold_crispy/layout/help_text.html,sha256=FY0UQv5FsoOFhrqvbILEfZE78Hj30r73YHCtg_MWNeY,207
255
+ unfold/templates/unfold_crispy/layout/help_text_and_errors.html,sha256=Um14wIg0FHthNM0mKE9VdptTrC-lTTcrDUO-UbbXxhY,108
256
+ unfold/templates/unfold_crispy/layout/radio_checkbox_select.html,sha256=pUlHC6j-fH62fAMiAZW-4BWXGD0RocHOKCmLtHN9pP8,997
257
+ unfold/templates/unfold_crispy/layout/row.html,sha256=MgGCI9s2mEn8C6xc78fb2Y4BsW6sbsKvgEd6aVRlFsg,184
258
+ unfold/templates/unfold_crispy/layout/table_inline_formset.html,sha256=QkKQU54uPTtFH58waipszk4SsQQw6mnBEqrzqgNsbls,4557
259
+ unfold/templates/unfold_crispy/uni_form.html,sha256=l9UNCUrIycgJ0p_B6qhtO_YxdARy3aq8qYY5h5BheSo,312
260
+ unfold/templates/unfold_crispy/whole_uni_form.html,sha256=ufXRKCIGqkqKFOsh166rpKUnHpFMyBV4eYUCRhs3iws,475
238
261
  unfold/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
239
- unfold/templatetags/unfold.py,sha256=JOjKCq2rfoKkqNqA7G6mjq2YvFt32jSLGKHxQ2cSluI,15987
262
+ unfold/templatetags/unfold.py,sha256=FcP69QNQ2_CPeqESvbxNax_VRw3WAE_R8Bjdkn4ZJuQ,16581
240
263
  unfold/templatetags/unfold_list.py,sha256=ayShOYEXcV3o7wKt3t2aFTWvg62Mb-WGlxjYVGgk3a0,14344
241
264
  unfold/typing.py,sha256=i7LM2LiwYTAjT5-OLDUPVn5b9X-DMmHnjlZG2toWwSE,692
242
265
  unfold/utils.py,sha256=SJikRuAuJN0bE9rfzUujZwycTRrzQm14Hk0zB0EwivU,6164
243
266
  unfold/views.py,sha256=FuYnMrlg6SegLUDDN6An__yZj8rchD_iBK8myieYhkA,1492
244
- unfold/widgets.py,sha256=eiFuIS6vWxEWwDBw9O6705ZWQa81wjWknbC37cCAFzA,20263
245
- django_unfold-0.53.0.dist-info/LICENSE.md,sha256=Ltk_quRyyvV3J5v3brtOqmibeZSw2Hrb8bY1W3ya0Ik,1077
246
- django_unfold-0.53.0.dist-info/METADATA,sha256=WSVzgcFxbK-zYYWdMsKJhBKusPR-u7Poh9d1KUGKgxI,5929
247
- django_unfold-0.53.0.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
248
- django_unfold-0.53.0.dist-info/RECORD,,
267
+ unfold/widgets.py,sha256=-l0eRljJheVWhTtD0nTvNuY1dvNmwtfd-aqXdSVr-q0,22344
268
+ django_unfold-0.55.0.dist-info/LICENSE.md,sha256=Ltk_quRyyvV3J5v3brtOqmibeZSw2Hrb8bY1W3ya0Ik,1077
269
+ django_unfold-0.55.0.dist-info/METADATA,sha256=6Wl1ju636FxUQ16ZKM9WFgvPOq5fdhX4S-I--r7XTqg,6977
270
+ django_unfold-0.55.0.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
271
+ django_unfold-0.55.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.1.1
2
+ Generator: poetry-core 2.1.2
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -2,6 +2,15 @@ from unfold.contrib.filters.admin.autocomplete_filters import (
2
2
  AutocompleteSelectFilter,
3
3
  AutocompleteSelectMultipleFilter,
4
4
  )
5
+ from unfold.contrib.filters.admin.choice_filters import (
6
+ AllValuesCheckboxFilter,
7
+ BooleanRadioFilter,
8
+ CheckboxFilter,
9
+ ChoicesCheckboxFilter,
10
+ ChoicesRadioFilter,
11
+ RadioFilter,
12
+ RelatedCheckboxFilter,
13
+ )
5
14
  from unfold.contrib.filters.admin.datetime_filters import (
6
15
  RangeDateFilter,
7
16
  RangeDateTimeFilter,
@@ -23,12 +32,20 @@ from unfold.contrib.filters.admin.numeric_filters import (
23
32
  from unfold.contrib.filters.admin.text_filters import FieldTextFilter, TextFilter
24
33
 
25
34
  __all__ = [
35
+ "AllValuesCheckboxFilter",
36
+ "BooleanRadioFilter",
37
+ "CheckboxFilter",
38
+ "ChoicesCheckboxFilter",
39
+ "ChoicesRadioFilter",
40
+ "MultipleRelatedCheckboxFilter",
41
+ "RadioFilter",
26
42
  "ChoicesDropdownFilter",
27
43
  "MultipleChoicesDropdownFilter",
28
44
  "DropdownFilter",
29
45
  "RelatedDropdownFilter",
30
46
  "MultipleDropdownFilter",
31
47
  "MultipleRelatedDropdownFilter",
48
+ "RelatedCheckboxFilter",
32
49
  "FieldTextFilter",
33
50
  "TextFilter",
34
51
  "RangeDateFilter",
@@ -0,0 +1,173 @@
1
+ from collections.abc import Generator
2
+ from typing import Any
3
+
4
+ from django.contrib import admin
5
+ from django.contrib.admin.views.main import ChangeList
6
+ from django.core.validators import EMPTY_VALUES
7
+ from django.db.models import QuerySet
8
+ from django.http import HttpRequest
9
+ from django.utils.translation import gettext_lazy as _
10
+
11
+ from unfold.contrib.filters.admin.mixins import (
12
+ ChoicesMixin,
13
+ MultiValueMixin,
14
+ ValueMixin,
15
+ )
16
+ from unfold.contrib.filters.forms import CheckboxForm, HorizontalRadioForm, RadioForm
17
+
18
+
19
+ class RadioFilter(admin.SimpleListFilter):
20
+ template = "unfold/filters/filters_field.html"
21
+ form_class = RadioForm
22
+ all_option = ["", _("All")]
23
+
24
+ def choices(self, changelist: ChangeList) -> tuple[dict[str, Any], ...]:
25
+ add_facets = changelist.add_facets
26
+ facet_counts = self.get_facet_queryset(changelist) if add_facets else None
27
+ choices = []
28
+
29
+ if self.all_option:
30
+ choices = [self.all_option]
31
+
32
+ if add_facets:
33
+ for i, (lookup, title) in enumerate(self.lookup_choices):
34
+ if (count := facet_counts.get(f"{i}__c", -1)) != -1:
35
+ title = f"{title} ({count})"
36
+ else:
37
+ title = f"{title} (-)"
38
+
39
+ choices.append((lookup, title))
40
+ else:
41
+ choices.extend(self.lookup_choices)
42
+
43
+ return (
44
+ {
45
+ "form": self.form_class(
46
+ label=_(" By %(filter_title)s ") % {"filter_title": self.title},
47
+ name=self.parameter_name,
48
+ choices=choices,
49
+ data={self.parameter_name: self.value()},
50
+ ),
51
+ },
52
+ )
53
+
54
+
55
+ class CheckboxFilter(RadioFilter):
56
+ form_class = CheckboxForm
57
+ all_option = None
58
+
59
+ def value(self) -> list[Any]:
60
+ return self.request.GET.getlist(self.parameter_name)
61
+
62
+
63
+ class ChoicesRadioFilter(ValueMixin, ChoicesMixin, admin.ChoicesFieldListFilter):
64
+ form_class = RadioForm
65
+ all_option = ["", _("All")]
66
+
67
+
68
+ class ChoicesCheckboxFilter(
69
+ MultiValueMixin, ChoicesMixin, admin.ChoicesFieldListFilter
70
+ ):
71
+ form_class = CheckboxForm
72
+ all_option = None
73
+
74
+
75
+ class BooleanRadioFilter(ValueMixin, admin.BooleanFieldListFilter):
76
+ template = "unfold/filters/filters_field.html"
77
+ form_class = HorizontalRadioForm
78
+ all_option = ["", _("All")]
79
+
80
+ def choices(self, changelist: ChangeList) -> Generator[dict[str, Any], None, None]:
81
+ add_facets = changelist.add_facets
82
+ facet_counts = self.get_facet_queryset(changelist) if add_facets else None
83
+
84
+ if add_facets:
85
+ choices = [
86
+ self.all_option,
87
+ *[
88
+ ("1", f"{_('Yes')} ({facet_counts['true__c']})"),
89
+ ("0", f"{_('No')} ({facet_counts['false__c']})"),
90
+ ],
91
+ ]
92
+ else:
93
+ choices = [
94
+ self.all_option,
95
+ *[
96
+ ("1", _("Yes")),
97
+ ("0", _("No")),
98
+ ],
99
+ ]
100
+
101
+ yield {
102
+ "form": self.form_class(
103
+ label=_(" By %(filter_title)s ") % {"filter_title": self.title},
104
+ name=self.lookup_kwarg,
105
+ choices=choices,
106
+ data={self.lookup_kwarg: self.value()},
107
+ ),
108
+ }
109
+
110
+
111
+ class RelatedCheckboxFilter(MultiValueMixin, admin.RelatedFieldListFilter):
112
+ template = "unfold/filters/filters_field.html"
113
+ form_class = CheckboxForm
114
+
115
+ def queryset(self, request: HttpRequest, queryset: QuerySet) -> QuerySet:
116
+ if self.value() not in EMPTY_VALUES:
117
+ return super().queryset(request, queryset)
118
+
119
+ return queryset
120
+
121
+ def choices(self, changelist: ChangeList) -> Generator[dict[str, Any], None, None]:
122
+ add_facets = changelist.add_facets
123
+ facet_counts = self.get_facet_queryset(changelist) if add_facets else None
124
+
125
+ if add_facets:
126
+ choices = []
127
+
128
+ for pk_val, val in self.lookup_choices:
129
+ count = facet_counts[f"{pk_val}__c"]
130
+ choice = (pk_val, f"{val} ({count})")
131
+ choices.append(choice)
132
+ else:
133
+ choices = self.lookup_choices
134
+
135
+ yield {
136
+ "form": self.form_class(
137
+ label=_(" By %(filter_title)s ") % {"filter_title": self.title},
138
+ name=self.lookup_kwarg,
139
+ choices=choices,
140
+ data={self.lookup_kwarg: self.value()},
141
+ ),
142
+ }
143
+
144
+
145
+ class AllValuesCheckboxFilter(MultiValueMixin, admin.AllValuesFieldListFilter):
146
+ template = "unfold/filters/filters_field.html"
147
+ form_class = CheckboxForm
148
+
149
+ def choices(self, changelist: ChangeList) -> Generator[dict[str, Any], None, None]:
150
+ add_facets = changelist.add_facets
151
+ facet_counts = self.get_facet_queryset(changelist) if add_facets else None
152
+
153
+ if add_facets:
154
+ choices = []
155
+
156
+ for i, val in enumerate(self.lookup_choices):
157
+ count = facet_counts[f"{i}__c"]
158
+ choice = (val, f"{val} ({count})")
159
+ choices.append(choice)
160
+ else:
161
+ choices = [[val, val] for _i, val in enumerate(self.lookup_choices)]
162
+
163
+ if len(choices) == 0:
164
+ return
165
+
166
+ yield {
167
+ "form": self.form_class(
168
+ label=_(" By %(filter_title)s ") % {"filter_title": self.title},
169
+ name=self.lookup_kwarg,
170
+ choices=choices,
171
+ data={self.lookup_kwarg: self.value()},
172
+ ),
173
+ }
@@ -86,11 +86,25 @@ class RelatedDropdownFilter(ValueMixin, DropdownMixin, admin.RelatedFieldListFil
86
86
  self.request = request
87
87
 
88
88
  def choices(self, changelist: ChangeList) -> Generator[dict[str, Any], None, None]:
89
+ add_facets = changelist.add_facets
90
+ facet_counts = self.get_facet_queryset(changelist) if add_facets else None
91
+
92
+ if add_facets:
93
+ choices = [self.all_option]
94
+
95
+ for pk_val, val in self.lookup_choices:
96
+ if add_facets:
97
+ count = facet_counts[f"{pk_val}__c"]
98
+ choice = (pk_val, f"{val} ({count})")
99
+ choices.append(choice)
100
+ else:
101
+ choices = [self.all_option, *self.lookup_choices]
102
+
89
103
  yield {
90
104
  "form": self.form_class(
91
105
  label=_(" By %(filter_title)s ") % {"filter_title": self.title},
92
106
  name=self.lookup_kwarg,
93
- choices=[self.all_option, *self.lookup_choices],
107
+ choices=choices,
94
108
  data={self.lookup_kwarg: self.value()},
95
109
  multiple=self.multiple if hasattr(self, "multiple") else False,
96
110
  ),
@@ -51,6 +51,31 @@ class DropdownMixin:
51
51
  return queryset
52
52
 
53
53
 
54
+ class ChoicesMixin:
55
+ template = "unfold/filters/filters_field.html"
56
+
57
+ def choices(self, changelist: ChangeList) -> Generator[dict[str, Any], None, None]:
58
+ add_facets = changelist.add_facets
59
+ facet_counts = self.get_facet_queryset(changelist) if add_facets else None
60
+ choices = [self.all_option] if self.all_option else []
61
+
62
+ for i, choice in enumerate(self.field.flatchoices):
63
+ if add_facets:
64
+ count = facet_counts[f"{i}__c"]
65
+ choice = (choice[0], f"{choice[1]} ({count})")
66
+
67
+ choices.append(choice)
68
+
69
+ yield {
70
+ "form": self.form_class(
71
+ label=_(" By %(filter_title)s ") % {"filter_title": self.title},
72
+ name=self.lookup_kwarg,
73
+ choices=choices,
74
+ data={self.lookup_kwarg: self.value()},
75
+ ),
76
+ }
77
+
78
+
54
79
  class RangeNumericMixin:
55
80
  request = None
56
81
  parameter_name = None
@@ -1,14 +1,20 @@
1
1
  from django import forms
2
+ from django.contrib.admin.options import HORIZONTAL
2
3
  from django.contrib.admin.widgets import AutocompleteSelect, AutocompleteSelectMultiple
3
4
  from django.db.models import Field as ModelField
4
- from django.forms import ChoiceField, ModelMultipleChoiceField, MultipleChoiceField
5
+ from django.forms import (
6
+ ChoiceField,
7
+ ModelMultipleChoiceField,
8
+ MultipleChoiceField,
9
+ )
5
10
  from django.http import HttpRequest
6
11
  from django.utils.translation import gettext_lazy as _
7
12
 
8
13
  from unfold.admin import ModelAdmin
9
-
10
- from ...widgets import (
14
+ from unfold.widgets import (
11
15
  INPUT_CLASSES,
16
+ UnfoldAdminCheckboxSelectMultiple,
17
+ UnfoldAdminRadioSelectWidget,
12
18
  UnfoldAdminSelectMultipleWidget,
13
19
  UnfoldAdminSelectWidget,
14
20
  UnfoldAdminSplitDateTimeVerticalWidget,
@@ -71,6 +77,38 @@ class AutocompleteDropdownForm(forms.Form):
71
77
  }
72
78
 
73
79
 
80
+ class CheckboxForm(forms.Form):
81
+ field = MultipleChoiceField
82
+ widget = UnfoldAdminCheckboxSelectMultiple
83
+
84
+ def __init__(
85
+ self,
86
+ name: str,
87
+ label: str,
88
+ choices: tuple,
89
+ *args,
90
+ **kwargs,
91
+ ) -> None:
92
+ super().__init__(*args, **kwargs)
93
+
94
+ self.fields[name] = self.field(
95
+ label=label,
96
+ required=False,
97
+ choices=choices,
98
+ widget=self.widget,
99
+ )
100
+
101
+
102
+ class RadioForm(CheckboxForm):
103
+ field = ChoiceField
104
+ widget = UnfoldAdminRadioSelectWidget
105
+
106
+
107
+ class HorizontalRadioForm(RadioForm):
108
+ horizontal = True
109
+ widget = UnfoldAdminRadioSelectWidget(radio_style=HORIZONTAL)
110
+
111
+
74
112
  class DropdownForm(forms.Form):
75
113
  widget = UnfoldAdminSelectWidget(
76
114
  attrs={
@@ -4,7 +4,7 @@
4
4
  <div class="flex flex-col">
5
5
  <h3 class="font-semibold mb-2 text-font-important-light dark:text-font-important-dark">{% blocktrans with filter_title=title %}By {{ filter_title }}{% endblocktrans %}</h3>
6
6
 
7
- <div class="flex flex-col space-y-4">
7
+ <div class="flex flex-col space-y-2">
8
8
  {% for field in choice.form %}
9
9
  <div class="flex flex-row flex-wrap group relative{% if field.errors %} errors{% endif %}">
10
10
  {{ field }}