django-unfold 0.52.0__py3-none-any.whl → 0.54.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 (42) hide show
  1. {django_unfold-0.52.0.dist-info → django_unfold-0.54.0.dist-info}/METADATA +1 -1
  2. {django_unfold-0.52.0.dist-info → django_unfold-0.54.0.dist-info}/RECORD +42 -38
  3. {django_unfold-0.52.0.dist-info → django_unfold-0.54.0.dist-info}/WHEEL +1 -1
  4. unfold/contrib/filters/admin/__init__.py +17 -0
  5. unfold/contrib/filters/admin/choice_filters.py +134 -0
  6. unfold/contrib/filters/admin/dropdown_filters.py +3 -3
  7. unfold/contrib/filters/admin/mixins.py +1 -1
  8. unfold/contrib/filters/admin/text_filters.py +2 -2
  9. unfold/contrib/filters/forms.py +41 -3
  10. unfold/contrib/filters/templates/unfold/filters/filters_date_range.html +1 -1
  11. unfold/contrib/filters/templates/unfold/filters/filters_datetime_range.html +1 -1
  12. unfold/contrib/filters/templates/unfold/filters/filters_numeric_slider.html +1 -1
  13. unfold/decorators.py +10 -4
  14. unfold/forms.py +2 -1
  15. unfold/paginator.py +10 -0
  16. unfold/sites.py +8 -6
  17. unfold/static/admin/js/inlines.js +23 -3
  18. unfold/static/unfold/css/styles.css +1 -1
  19. unfold/styles.css +2 -1
  20. unfold/templates/admin/auth/user/add_form.html +1 -1
  21. unfold/templates/admin/change_form.html +9 -8
  22. unfold/templates/admin/change_list.html +15 -13
  23. unfold/templates/admin/change_list_results.html +1 -1
  24. unfold/templates/admin/edit_inline/tabular.html +1 -2
  25. unfold/templates/admin/pagination.html +4 -20
  26. unfold/templates/unfold/components/chart/cohort.html +2 -2
  27. unfold/templates/unfold/helpers/change_list_filter.html +2 -2
  28. unfold/templates/unfold/helpers/change_list_filter_actions.html +28 -26
  29. unfold/templates/unfold/helpers/edit_inline/tabular_field.html +10 -8
  30. unfold/templates/unfold/helpers/field.html +4 -2
  31. unfold/templates/unfold/helpers/fieldset_row.html +19 -7
  32. unfold/templates/unfold/helpers/form_label.html +1 -1
  33. unfold/templates/unfold/helpers/pagination_default.html +23 -0
  34. unfold/templates/unfold/helpers/pagination_infinite.html +11 -0
  35. unfold/templates/unfold/helpers/site_icon.html +14 -14
  36. unfold/templates/unfold/helpers/tab_action.html +18 -3
  37. unfold/templates/unfold/helpers/welcomemsg.html +2 -2
  38. unfold/templates/unfold/widgets/radio_option.html +1 -1
  39. unfold/templatetags/unfold.py +66 -29
  40. unfold/utils.py +11 -0
  41. unfold/widgets.py +2 -0
  42. {django_unfold-0.52.0.dist-info → django_unfold-0.54.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.52.0
3
+ Version: 0.54.0
4
4
  Summary: Modern Django admin theme for seamless interface development
5
5
  License: MIT
6
6
  Keywords: django,admin,tailwind,theme
@@ -5,26 +5,27 @@ 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=pDBGb4uAbAKgZB3ChEVRy6us20JktRtdDfCjquPJKa4,4377
10
11
  unfold/contrib/filters/admin/datetime_filters.py,sha256=cVari_7jsfeYxJoRBhcAUOr6v9XdtDtMuMs-S1Irafo,7757
11
- unfold/contrib/filters/admin/dropdown_filters.py,sha256=YiPLakTIzLuojULfpctFV0aP8DwfWLDnU-lcjoK2qnE,3354
12
- unfold/contrib/filters/admin/mixins.py,sha256=djaM5kxQFvl64GkNnhbCyo78UVNhDb0CIDiSNUXkUGo,4943
12
+ unfold/contrib/filters/admin/dropdown_filters.py,sha256=aZhBTEjtbeaOdYZK4nYRmA38usy9rhVTM4L_08MGU0I,3360
13
+ unfold/contrib/filters/admin/mixins.py,sha256=iOO89KpVmKig_4RPJem2TqIwZO-ROUjGTmoDmBkgyLk,4945
13
14
  unfold/contrib/filters/admin/numeric_filters.py,sha256=8GNmesgMmMIfEZb2IrGbaBoJuvB2FpIc7wPIPBpHat4,6420
14
- unfold/contrib/filters/admin/text_filters.py,sha256=NXyKm0Ed24N9pNfR7Dys5kTpZ_V5FUurdxk7KDMdRIg,2084
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
27
- unfold/contrib/filters/templates/unfold/filters/filters_numeric_slider.html,sha256=E-OrYbFNKSyNc2yaoDB9LLuiDd_ShU5hJGlLij35NYs,1714
28
+ unfold/contrib/filters/templates/unfold/filters/filters_numeric_slider.html,sha256=UDhcNnDmP9ab6UMvikRp7tNVQazoh_fUds29yhWOljs,1724
28
29
  unfold/contrib/forms/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
30
  unfold/contrib/forms/apps.py,sha256=Di0TMzVuRpVxLG-8Bjdq5ALCSf5r7u2xVhD0jU6H5Sc,132
30
31
  unfold/contrib/forms/static/unfold/forms/css/trix.css,sha256=TH9WdnaZrmwI8hAEydwjobdrBzSw_KYdRTSQDuD-8hE,20027
@@ -72,22 +73,23 @@ unfold/contrib/simple_history/templates/simple_history/object_history_form.html,
72
73
  unfold/contrib/simple_history/templates/simple_history/object_history_list.html,sha256=ls_xEAAgGzbu0IXdjZk7scEyEJx0S7i3Khr9ND98gzY,6842
73
74
  unfold/contrib/simple_history/templates/simple_history/submit_line.html,sha256=y8BleGHPNztA_R37rTB-zjJ68uDbE8flYSvMD0Jfl5Y,1734
74
75
  unfold/dataclasses.py,sha256=a-9INnkCAIcnMgoffTcB1rxWCJH33AjhMCWIGWnjWbI,719
75
- unfold/decorators.py,sha256=5fxobPFVlx4i-ldLm6M_ln3jFl261ZMKCcv9aXvXMVA,4082
76
+ unfold/decorators.py,sha256=15X9FdoKkgxweUqIboH7kiDrBheT3uBEFNT-JummEl0,4297
76
77
  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
- unfold/forms.py,sha256=BKv7eCbv29eCIuf1d_ZBmD4-_OIIzRaopiFd2nKbXNY,4520
80
+ unfold/forms.py,sha256=3MrVG9jDdDsrJHph-cimZXRycfdoAw-KhT0uJJInG7E,4552
80
81
  unfold/mixins/__init__.py,sha256=YlhoDs9Y_DXQ8Ejr3enxuHMS1-Ij9fwukxNwpeOS4Co,190
81
82
  unfold/mixins/action_model_admin.py,sha256=BPajuTGf7zAaZOqIq4shX8VQ3NTxWQpedvG58fmCTjk,12036
82
83
  unfold/mixins/base_model_admin.py,sha256=PR4eqU48yB4CNy9Bjd7fjxbOFiFpZM4etYmBOSaRX_M,4140
83
84
  unfold/overrides.py,sha256=ERVY9boZiXgjDYcTEZcIp7KWoeBZ45VM_zN31yAOjyQ,2922
85
+ unfold/paginator.py,sha256=vWCIfpuWbV3nvIkQOPyD7MLTg2hZplHz3rze42d-qiA,268
84
86
  unfold/sections.py,sha256=Lcg3xCZ76fqjm4vD4x7YdE5VsbTKluL-sX5QTEBlHxA,2379
85
87
  unfold/settings.py,sha256=3ICha2I0oSaHhajG8159nHdNTYJInBtRQq9VziWKYKs,2709
86
- unfold/sites.py,sha256=Pl8voDdMH_9RV1n3XmSz84T6OE8yDUAqNwlr-kPH1n8,16179
88
+ unfold/sites.py,sha256=fx3U0kIfN3My4UNiXO_ggrudmFvYNglMAIARaMa2gqY,16321
87
89
  unfold/static/admin/js/admin/RelatedObjectLookups.js,sha256=alI0-yq7YPDJJJn-yg1ce79-Cv88yQDUrfaGqFZnsaY,9048
88
- unfold/static/admin/js/inlines.js,sha256=74QODSKEkpKse4bft4wIFZquROcr2-hVTt9CEWOIJak,15061
90
+ unfold/static/admin/js/inlines.js,sha256=zcYwLGI_6RHg-gucDbbhp43RRoZd3so8bPk841KFaIE,15573
89
91
  unfold/static/unfold/css/simplebar.css,sha256=5LLaEM11pKi6JFCOLt4XKuZxTpT9rpdq_tNlaQytFlU,4647
90
- unfold/static/unfold/css/styles.css,sha256=QfcKos7Ys3mtWm3Q6BmsAkytkpoXIjQzM3D0P_A3FY4,160310
92
+ unfold/static/unfold/css/styles.css,sha256=-tB48trW_4YUmPdnHYP31ulsXOPiwsC6s6hHffmDW_w,161933
91
93
  unfold/static/unfold/fonts/inter/Inter-Bold.woff2,sha256=-oiBJ7baAVtlVp8DUfO1w5GtkokElR8cIOn4RiqNleo,114840
92
94
  unfold/static/unfold/fonts/inter/Inter-Medium.woff2,sha256=D_PpRhThST61VjFP0keubEqFp3g7TMhr5TmUDPg_Kkg,114348
93
95
  unfold/static/unfold/fonts/inter/Inter-Regular.woff2,sha256=4G9rG8VTqupORmgCPtCrChRxKcMQf1Ebx9A9NhsK4IU,111268
@@ -105,24 +107,24 @@ unfold/static/unfold/js/chart.js,sha256=22W6cFERR-CElMOKRgMMicueMVP0Vf7FBEBYH8Z8
105
107
  unfold/static/unfold/js/htmx.js,sha256=acrv0NqSJpBm5yXX_hdeJrnVDJYuMFZFnAxHcVTNudM,50918
106
108
  unfold/static/unfold/js/select2.init.js,sha256=gXZngZh-l5ID2-VmndpGseNi6A0zKB18UgPyCor68CU,1040
107
109
  unfold/static/unfold/js/simplebar.js,sha256=t-uG1FAD6ZoiMeN--wac0XRS7SxoDVG6zvRnGuEp7X8,27176
108
- unfold/styles.css,sha256=6lYnrPCD8anvFHGN9DZJFsW8iDn7T3qvP-i8zNWulpo,19112
110
+ unfold/styles.css,sha256=Mbe0mO2608aH3bCVllxTKb6OcsMIy-ZAugcwaWBwM0E,19142
109
111
  unfold/templates/admin/actions.html,sha256=aroIid16mORcx-0p8O2dOoWupEoTGX66pt-PAXjSYZ0,3063
110
112
  unfold/templates/admin/app_index.html,sha256=GSBry97gDcK3scTP-Fs4FXcSItRxxE87Wv4sDtMTlbc,1244
111
113
  unfold/templates/admin/app_list.html,sha256=VtntgHpbZdXbt_HXBLAtbuMdz1alS7F_S7eG37M5Rig,2855
112
- unfold/templates/admin/auth/user/add_form.html,sha256=kZDtUyhrvCIH9rlAq0iXLKYt97j1a-GsrWZQCQDASYM,479
114
+ unfold/templates/admin/auth/user/add_form.html,sha256=37sLn-uhMh5vt0wCaL9lu1IPzdJlfq9HGpRYbTZLcEw,478
113
115
  unfold/templates/admin/auth/user/change_password.html,sha256=OxpsKnVQm5lDrK5tGH0EAPFCPs288m0Jcy5WNYsdBXw,2896
114
116
  unfold/templates/admin/base.html,sha256=3xQmoD_7cu2UlgEdvnt7v_CibT9t1Iul0b-VU2Awu_U,2395
115
117
  unfold/templates/admin/base_site.html,sha256=UOsecaCycpyn_ygJNIKO7MQtDFJuHv--r83-mzaVY30,300
116
- unfold/templates/admin/change_form.html,sha256=TsKop_uAiuM3LLlW5YQ-9-zsTpbnOnCfIF2yMUn7NB8,5408
118
+ unfold/templates/admin/change_form.html,sha256=ZVOtRNTppyhWddRs3qdyWIznWXRl6QGsIzDO8-C-Puk,5665
117
119
  unfold/templates/admin/change_form_object_tools.html,sha256=eyeH-i2HgEM0Yi-OJA2D1VnKJyC19A_my1IDGxxoP8Y,593
118
- unfold/templates/admin/change_list.html,sha256=AhGUdt-S3m30WhSraWnBdLwZQ1JU9yZeVDL0WDqCEMI,5164
120
+ unfold/templates/admin/change_list.html,sha256=o3nPQUHo9rCpaNfoGfBl1owhIDvk_gwSESbCP0bK_YQ,5291
119
121
  unfold/templates/admin/change_list_object_tools.html,sha256=cmMiT2nT20Ph5yfpj9aHPr76Z-JP4aSXp0o-Rnad28s,147
120
- unfold/templates/admin/change_list_results.html,sha256=n64K5ocS62kujxzzkojzOx4jJuiYcO8r4mcJfcsCQAs,7931
122
+ unfold/templates/admin/change_list_results.html,sha256=H7JtxfZSRIwYQTYdBAumFpkATETSE2rvNgwCsUSGzno,7931
121
123
  unfold/templates/admin/date_hierarchy.html,sha256=Jl_Vk05fXvsSvod5Dw2p3KhpCQGjtSX1zqlNjjkBFR4,1411
122
124
  unfold/templates/admin/delete_confirmation.html,sha256=yT_NHbFHZEjkSCaGVcM52GCG-FDmWiJdTFLbq9CBCx4,4619
123
125
  unfold/templates/admin/delete_selected_confirmation.html,sha256=QR0JhrPR8YI8KpQnB3xyrKxaui-_pEQmfaMDbcXjjZ0,4391
124
126
  unfold/templates/admin/edit_inline/stacked.html,sha256=-ASy7Jd0SwWBDxurucbus86YT2AokJEcCUrqPlHVDQA,7644
125
- unfold/templates/admin/edit_inline/tabular.html,sha256=FBgzUb-U0cZCN28-cpHzRSyPE6bgseD_r3MY1AP0nGQ,2813
127
+ unfold/templates/admin/edit_inline/tabular.html,sha256=GFXgOwMK0WZfFtMdfw7JMAXTUmW7cavEh9FYQ2dTgh4,2893
126
128
  unfold/templates/admin/filter.html,sha256=0B_hpLybHw1wUPPCN3KJvoWrx03iFeqP8m1LRCjnLlQ,2012
127
129
  unfold/templates/admin/includes/fieldset.html,sha256=gX-dc-jPLswk21XSKUXzAU8WFl3CFfeVrIAU2bviPyg,812
128
130
  unfold/templates/admin/includes/object_delete_summary.html,sha256=FgwfapZCKWtnFtTHqh1MRuxxLot4bAw92WCcR_V8ImI,444
@@ -130,7 +132,7 @@ unfold/templates/admin/index.html,sha256=JnNDpNKqFKVKMQvpUQo6ddcFqGadK5g78pxpKAH
130
132
  unfold/templates/admin/login.html,sha256=5khGm_cafDVQaDRwaTtix4g2DH4R4LrwgqO0S4aumaE,4476
131
133
  unfold/templates/admin/nav_sidebar.html,sha256=cadJwXcReRHwVTpXGycF3uv5VZ5JDcIbY1pCabeQlCo,250
132
134
  unfold/templates/admin/object_history.html,sha256=bfad4_lfLQFcoMV67yW7BnAi1Hwrptmgxj2tgPYQjtI,4816
133
- unfold/templates/admin/pagination.html,sha256=1UIc6Hm2LnDDAHUE5UjuPzdFdiAat4tF6sk058UfRP0,2251
135
+ unfold/templates/admin/pagination.html,sha256=k0OfgbKSu6HzP0zfAOHC4hswFk1Xc8XEQYfuqJxQQT4,1734
134
136
  unfold/templates/admin/search_form.html,sha256=eQkwq4OWVgNUSjZPzxAjtT4LcxUNcTSgDVKJ4lWwslQ,1447
135
137
  unfold/templates/admin/submit_line.html,sha256=GN86RzCT3aETQDC5ROMWesxf0QhqIFD218jee_P1_u4,4832
136
138
  unfold/templates/auth/widgets/read_only_password_hash.html,sha256=bQiYKDKJkyVP0_2eJG16oKviB4WEA0V7lSp6sGfgows,751
@@ -140,7 +142,7 @@ unfold/templates/registration/password_change_form.html,sha256=EgakVWzpQUEJKQS0A
140
142
  unfold/templates/unfold/components/button.html,sha256=TABo79ppuGlm2ENvRs6L3Vne8B5_9he_OhZTnPMiitQ,473
141
143
  unfold/templates/unfold/components/card.html,sha256=FVLN7kQZqMd_uhEi1LpiN9FUxZCa4RgGHYGmofCtQro,1141
142
144
  unfold/templates/unfold/components/chart/bar.html,sha256=nDdDCUXvFd793OpNgNPQo0vBmvYngMsQyPHVTf1vfOw,297
143
- unfold/templates/unfold/components/chart/cohort.html,sha256=elZj9e9E9cfVey_9LSOaDoVSE3Wn3BagSrwIXRSFadM,2354
145
+ unfold/templates/unfold/components/chart/cohort.html,sha256=wDjRb2IT1XEJ--Y1BrSaMOeM7XXy9iohJR_4RZ2ilSs,2362
144
146
  unfold/templates/unfold/components/chart/line.html,sha256=DHaZUFTlCs5cX7ioYdTzoN4ITHWNcEoNSUp7v3hlo_E,298
145
147
  unfold/templates/unfold/components/container.html,sha256=WBk1rGHnTsObi3pJCpL3dfFAUQ2abDmokU0Lee7R9CI,83
146
148
  unfold/templates/unfold/components/flex.html,sha256=_hBsQLJ6-7MfEfXNp5Wy-ykNtPMnnNg_io2IMGegn3s,134
@@ -161,28 +163,28 @@ unfold/templates/unfold/helpers/attrs.html,sha256=Mwpj72kuwYj8hOT3J2T8qx6f1r_4xw
161
163
  unfold/templates/unfold/helpers/boolean.html,sha256=kcSZr3siQeBWIy_jsx1tFf4m6IB3ooRnu8UUNQrh6so,569
162
164
  unfold/templates/unfold/helpers/breadcrumb_item.html,sha256=9T6ojN7LOXIlgwSwlIwHgy5U22eQYtarCqcmzsQIoPU,201
163
165
  unfold/templates/unfold/helpers/change_list_actions.html,sha256=p1_vC2Q_Fb-gAHA8y1zzOXqqn5TPQMrQfE26PkOY_ok,656
164
- unfold/templates/unfold/helpers/change_list_filter.html,sha256=0l-c4H2PcDkAuzI6asAJf2rBfYavYG62F9d7yWWdkSI,1852
165
- unfold/templates/unfold/helpers/change_list_filter_actions.html,sha256=fTlM6jyS83FhGulFYuhFVLJOGHRJV3mFCWDQnp1kp0U,1760
166
+ unfold/templates/unfold/helpers/change_list_filter.html,sha256=oAWtb29vT0g2myp7IqLr_a7O72TboxUskwOEId4ZnpY,1921
167
+ unfold/templates/unfold/helpers/change_list_filter_actions.html,sha256=_D_ub3xh9sJFiM4BbmfdlvZzXb8rXQEwY9yQn6KM2Xc,1973
166
168
  unfold/templates/unfold/helpers/delete_submit_line.html,sha256=N1w_TDIDN7Spj5diuhRUVOVgz2TiSeHVK2QvBjTLv2w,665
167
169
  unfold/templates/unfold/helpers/display_dropdown.html,sha256=e83t_lR2uSxnNoDYKnTKyD57V3FTMCM9T0h0DeFdAV8,2850
168
170
  unfold/templates/unfold/helpers/display_header.html,sha256=rhru2GSxR0mH8_FEQuQVIS8gGGjaiWMV9f2HCPGMsaQ,1698
169
171
  unfold/templates/unfold/helpers/display_label.html,sha256=LS9DWzYjHkYLV27sZDwyXlg2sLJ0AlId9FbjnXpsbfg,317
170
172
  unfold/templates/unfold/helpers/edit_inline/tabular_delete.html,sha256=KFp6d8whXp2DlRyHJF1OsCkJa3Vy-UU-nkQXSlpuui0,928
171
173
  unfold/templates/unfold/helpers/edit_inline/tabular_error.html,sha256=8XGlgUJ47JllmXhwPZDlcl81NzZmvuBIp8FZBWoeu9Q,336
172
- unfold/templates/unfold/helpers/edit_inline/tabular_field.html,sha256=BRCAXdv-HBWyhKK__whswrNiXIH6roexbTKo1w41Btc,919
174
+ unfold/templates/unfold/helpers/edit_inline/tabular_field.html,sha256=JDcSvqozjjNB1wAXcmJCi1xI1iXQAIxylHz4PYTPMkU,1002
173
175
  unfold/templates/unfold/helpers/edit_inline/tabular_heading.html,sha256=ER8R64wnKOu26WTwP4_Wxt-LRB_zRkXLhheZ_utVvKY,1523
174
176
  unfold/templates/unfold/helpers/edit_inline/tabular_row.html,sha256=Cfs2m5eh3mLcMgL0_dSAokAscgq4q19KsnUPZECmDgw,2013
175
177
  unfold/templates/unfold/helpers/edit_inline/tabular_title.html,sha256=JPSue6mD1-KZ3tiymbRrv1G2XgsSim4cT_6HhzYJaYY,2710
176
178
  unfold/templates/unfold/helpers/empty_results.html,sha256=KV9DLKLURDtlkjDI88u05l6cXiOoeSv1nR4wFNIQ2hE,1933
177
- unfold/templates/unfold/helpers/field.html,sha256=Ds-zUHkdyxamfUCVNhxvtM0XoJg9OCA0QcsLbLWv4oo,882
179
+ unfold/templates/unfold/helpers/field.html,sha256=awM8lUlERpPSSz9TczWrMvxXzY8jGbEvix0JzWvHMVE,979
178
180
  unfold/templates/unfold/helpers/field_readonly.html,sha256=4qtXjWE7SA2qZSTYLOv0lT4pQfD0TE34mvWQJY7jhS8,237
179
181
  unfold/templates/unfold/helpers/field_readonly_value.html,sha256=6DNteF8x6_tihQZVCGgz2CqB0ogsLRJhxgDep0sHguc,464
180
- unfold/templates/unfold/helpers/fieldset_row.html,sha256=GSrMJZSNY1Tn6y3APOAeADg8Vdsa9QO_RMtj4I2SvQM,445
182
+ unfold/templates/unfold/helpers/fieldset_row.html,sha256=LriorPLXU4VmqstjX1oBc3T49H8CbhCrRxwQ7YfUSkI,1219
181
183
  unfold/templates/unfold/helpers/fieldset_row_checkbox.html,sha256=fJh5dZstm8f8pPTbN1pg5VSYPkQB4EnqSfh9RpsxdXk,1472
182
184
  unfold/templates/unfold/helpers/fieldset_row_field.html,sha256=xXxmELXMXzbNclp36rQn_09Uekq-RQkDP3kRT0Bp6rA,643
183
185
  unfold/templates/unfold/helpers/fieldsets_tabs.html,sha256=KW2rzVqpIICEu55GR_KnuOoXOGnqTZOQAKIuW-u8cAU,1459
184
186
  unfold/templates/unfold/helpers/form_errors.html,sha256=EwerIJptSCWXvtAJ1IZKfEn98qlShBIGavsTThbklAs,266
185
- unfold/templates/unfold/helpers/form_label.html,sha256=BRX3DxVQfEvcmpFcRuhl4v_icMCCd5O_zmYm6MGLtts,327
187
+ unfold/templates/unfold/helpers/form_label.html,sha256=7FfaXfviQmqKpsA1E7NSwM8rJiMNLl9e73XQram0Pfs,249
186
188
  unfold/templates/unfold/helpers/header.html,sha256=ZoQH_Fs1v7fbo6fWQ5UEgfM9xPQlsYQxeabLf7nndB8,1050
187
189
  unfold/templates/unfold/helpers/header_back_button.html,sha256=6DXkxsZJnIt0Z_AILDJNlj1gntEetFD-_b40mWFXwro,413
188
190
  unfold/templates/unfold/helpers/help_text.html,sha256=o-2_hyruIr_Xt0fo38aGgrpptPJFhddnVMPOVQOYhE4,113
@@ -199,21 +201,23 @@ unfold/templates/unfold/helpers/messages.html,sha256=I9RIKfi4T65AG16-2s0C32RwbFk
199
201
  unfold/templates/unfold/helpers/navigation.html,sha256=HNr9bxZOg84zsbgORkOhJFXKSp0c2im438yiWCfonb0,787
200
202
  unfold/templates/unfold/helpers/navigation_header.html,sha256=upSSMGsqVzk_HfNINcapUtmR_d8kV2yxdwPEjMbRknY,1402
201
203
  unfold/templates/unfold/helpers/pagination_current_item.html,sha256=4cZ2KLVcP0Y7xuGyXgexDQ07r94cgM5Gnmtv11dkRPQ,69
204
+ unfold/templates/unfold/helpers/pagination_default.html,sha256=pseTrqaG5EOn_IpCy0GXNht3ickSkZYJ4lJaocZeI6A,496
202
205
  unfold/templates/unfold/helpers/pagination_ellipsis.html,sha256=8g0KUUKtqRkXx_EBLGtsJsiYQO4tPS3GazZjxT90e0M,56
206
+ unfold/templates/unfold/helpers/pagination_infinite.html,sha256=-U1i-90jxzJVui56NvuJ1OxrywN8QLrs-IRu9KLmN20,422
203
207
  unfold/templates/unfold/helpers/search.html,sha256=w8Ute3qVfSIqUXzA3TKOx91RzW_qnffFi2Oe9qedtV4,1643
204
208
  unfold/templates/unfold/helpers/search_results.html,sha256=5gxOAfFBPOkRgDziyYio6ZXcDG1bzFw7t-KXGFaWrUk,653
205
209
  unfold/templates/unfold/helpers/site_branding.html,sha256=_pUyOvdjlV624eRq0wjpJkgXpn9DCDGc-0U6Mw0FupI,266
206
210
  unfold/templates/unfold/helpers/site_dropdown.html,sha256=Zwg5ZGVIEHAI2h-YcWDDBz3QD2nYsP9m530wYArFk5I,878
207
- unfold/templates/unfold/helpers/site_icon.html,sha256=rB6oc6VBB0T7wtyGOPcrq6qepDRaA54F6-Wxtaru-ks,1297
211
+ unfold/templates/unfold/helpers/site_icon.html,sha256=qSEpI1RrNlk6ad6HDiBa74vjsYqGgmEgVbfSXdyyMLI,1485
208
212
  unfold/templates/unfold/helpers/site_logo.html,sha256=S_QJoT2qh0xw0ciaKxoT4GJ6QIH5eqgRSC0abbWWkOI,423
209
213
  unfold/templates/unfold/helpers/submit.html,sha256=4Mgf4lx7Atm8GPqD6LTJK3NA9zoSJjs9VPig7sDp8Ao,203
210
- unfold/templates/unfold/helpers/tab_action.html,sha256=6N6Xi7XGtweS6gt0oZrVu6AIaJ9WIQSH-mpndn0CCYE,2263
214
+ unfold/templates/unfold/helpers/tab_action.html,sha256=ODm7ws5sbhpE4OvGuQbzynlVwk6AJRreMUra6hh1lxM,3306
211
215
  unfold/templates/unfold/helpers/tab_actions.html,sha256=DMNqY1YyrNrcutOMC3J1neZZjIkPeYShp1i5xZ10nrc,695
212
216
  unfold/templates/unfold/helpers/tab_items.html,sha256=Gi6cjYJ7tJWO6zSXjg8xNHY9ALpYzjQOEORusf_AZfg,3325
213
217
  unfold/templates/unfold/helpers/tab_list.html,sha256=Tqkug9GyoIQ2geVKWrnnuE0bxeTRXj0MSEwwixoOGz4,436
214
218
  unfold/templates/unfold/helpers/theme_switch.html,sha256=Kh3Q8RuBWCUuY8YJLwBwd5yKzDhK6y0Ggx_ERoGEGv8,2218
215
219
  unfold/templates/unfold/helpers/userlinks.html,sha256=oZqiwCxG_zRecAbzYrr8_hQvkndVB6-liP6LEZM1UZc,863
216
- unfold/templates/unfold/helpers/welcomemsg.html,sha256=a7VjZ8J1mn-DAo57nhUP096SEcBOqcCWrWt2qoT0cyg,1882
220
+ unfold/templates/unfold/helpers/welcomemsg.html,sha256=uncDEg3j6NsSKCGOA7uVY-GCxsacktV3-bQrd-vn5FU,1940
217
221
  unfold/templates/unfold/layouts/base.html,sha256=e9T-vuPvrySHf23LLwRuTQXUg0Q4x-6gmT_yXghqc-I,278
218
222
  unfold/templates/unfold/layouts/base_simple.html,sha256=VigjNWnWOt_XtbahvqsroPf8mdwl7cDGbg5fEaLmG9s,1211
219
223
  unfold/templates/unfold/layouts/skeleton.html,sha256=TmZ0hX5j7McwSiYcdGGuhAjDunPDCWtPC7lDF6hbtDk,4641
@@ -223,7 +227,7 @@ unfold/templates/unfold/widgets/clearable_file_input_small.html,sha256=NNlosUwhz
223
227
  unfold/templates/unfold/widgets/date.html,sha256=ih9wj8koTaHb9s1NGUmyN9rHvSAmqCMbti9ONDOIujg,122
224
228
  unfold/templates/unfold/widgets/foreign_key_raw_id.html,sha256=7-JPapXS2Ty0MLXNdZ1jCuydqc6JyDs-8-w9b8TcmVU,1075
225
229
  unfold/templates/unfold/widgets/radio.html,sha256=7Mgc92mMwJdVLjCxoGj5lo76KNaN5dKKktV3vzmbeqA,652
226
- unfold/templates/unfold/widgets/radio_option.html,sha256=UVgNUd_DuIHc4tRpnvYnJwG67PycYT2sBAyuVGAY0RM,307
230
+ unfold/templates/unfold/widgets/radio_option.html,sha256=wVg6zIB0O44vwBgQCCphPuCXeh-gaDg6ed-0gcf5kg4,324
227
231
  unfold/templates/unfold/widgets/range.html,sha256=Zhfj2VTusS3nZjOYR7slcjk1JtFK0psZbaSCw6TDY1I,294
228
232
  unfold/templates/unfold/widgets/related_widget_wrapper.html,sha256=4RsFmwlm6De85wsP6W4PvqKosNUPKKNb95RIRh0UUgs,3895
229
233
  unfold/templates/unfold/widgets/split_datetime.html,sha256=2-k9cF1iAeYp3iUT4_9KIIDyZEG3Z25ls34dLan9Z3M,1094
@@ -233,13 +237,13 @@ unfold/templates/unfold/widgets/textarea.html,sha256=-ZLDGrtASero7L-J3VvTNq_KjPA
233
237
  unfold/templates/unfold/widgets/time.html,sha256=ih9wj8koTaHb9s1NGUmyN9rHvSAmqCMbti9ONDOIujg,122
234
238
  unfold/templates/unfold/widgets/url.html,sha256=IRLgW44VTKN7UrSWeywJwaxQhfG5jhhXuT-KTadKX58,304
235
239
  unfold/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
236
- unfold/templatetags/unfold.py,sha256=rNpa1B9bEM-HQRWEss4PZ_nwnTRR8L3J12qOcjR5A_k,14550
240
+ unfold/templatetags/unfold.py,sha256=yPSNtaBDiiJh6VNhl3VPDJ-jsX69pbnIf4JolEnw290,16239
237
241
  unfold/templatetags/unfold_list.py,sha256=ayShOYEXcV3o7wKt3t2aFTWvg62Mb-WGlxjYVGgk3a0,14344
238
242
  unfold/typing.py,sha256=i7LM2LiwYTAjT5-OLDUPVn5b9X-DMmHnjlZG2toWwSE,692
239
- unfold/utils.py,sha256=oB71xynQQEXj055BkTVwc4pz5hXk6tipFBAIU8TWDyA,5838
243
+ unfold/utils.py,sha256=SJikRuAuJN0bE9rfzUujZwycTRrzQm14Hk0zB0EwivU,6164
240
244
  unfold/views.py,sha256=FuYnMrlg6SegLUDDN6An__yZj8rchD_iBK8myieYhkA,1492
241
- unfold/widgets.py,sha256=eiFuIS6vWxEWwDBw9O6705ZWQa81wjWknbC37cCAFzA,20263
242
- django_unfold-0.52.0.dist-info/LICENSE.md,sha256=Ltk_quRyyvV3J5v3brtOqmibeZSw2Hrb8bY1W3ya0Ik,1077
243
- django_unfold-0.52.0.dist-info/METADATA,sha256=u958OA_otWoONnSKCrFKghqfe_j_9r6LzyZAJD0c2uE,5929
244
- django_unfold-0.52.0.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
245
- django_unfold-0.52.0.dist-info/RECORD,,
245
+ unfold/widgets.py,sha256=1uyGsw-xA0qspf7Uzic47GVN5xv4L_sVfL-elqlxgm0,20293
246
+ django_unfold-0.54.0.dist-info/LICENSE.md,sha256=Ltk_quRyyvV3J5v3brtOqmibeZSw2Hrb8bY1W3ya0Ik,1077
247
+ django_unfold-0.54.0.dist-info/METADATA,sha256=jKgXXRccydhPXLehmUQkHA_xcBzY2XulaY2fB04a_NA,5929
248
+ django_unfold-0.54.0.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
249
+ django_unfold-0.54.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,134 @@
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 MultiValueMixin, ValueMixin
12
+ from unfold.contrib.filters.forms import CheckboxForm, HorizontalRadioForm, RadioForm
13
+
14
+
15
+ class RadioFilter(admin.SimpleListFilter):
16
+ template = "unfold/filters/filters_field.html"
17
+ form_class = RadioForm
18
+ all_option = ["", _("All")]
19
+
20
+ def choices(self, changelist: ChangeList) -> tuple[dict[str, Any], ...]:
21
+ if self.all_option:
22
+ choices = [self.all_option, *self.lookup_choices]
23
+ else:
24
+ choices = self.lookup_choices
25
+
26
+ return (
27
+ {
28
+ "form": self.form_class(
29
+ label=_(" By %(filter_title)s ") % {"filter_title": self.title},
30
+ name=self.parameter_name,
31
+ choices=choices,
32
+ data={self.parameter_name: self.value()},
33
+ ),
34
+ },
35
+ )
36
+
37
+
38
+ class CheckboxFilter(RadioFilter):
39
+ form_class = CheckboxForm
40
+ all_option = None
41
+
42
+
43
+ class ChoicesMixin:
44
+ template = "unfold/filters/filters_field.html"
45
+
46
+ def choices(self, changelist: ChangeList) -> Generator[dict[str, Any], None, None]:
47
+ if self.all_option:
48
+ choices = [self.all_option, *self.field.flatchoices]
49
+ else:
50
+ choices = self.field.flatchoices
51
+
52
+ yield {
53
+ "form": self.form_class(
54
+ label=_(" By %(filter_title)s ") % {"filter_title": self.title},
55
+ name=self.lookup_kwarg,
56
+ choices=choices,
57
+ data={self.lookup_kwarg: self.value()},
58
+ ),
59
+ }
60
+
61
+
62
+ class ChoicesRadioFilter(ValueMixin, ChoicesMixin, admin.ChoicesFieldListFilter):
63
+ form_class = RadioForm
64
+ all_option = ["", _("All")]
65
+
66
+
67
+ class ChoicesCheckboxFilter(ValueMixin, ChoicesMixin, admin.ChoicesFieldListFilter):
68
+ form_class = CheckboxForm
69
+ all_option = None
70
+
71
+
72
+ class BooleanRadioFilter(ValueMixin, admin.BooleanFieldListFilter):
73
+ template = "unfold/filters/filters_field.html"
74
+ form_class = HorizontalRadioForm
75
+ all_option = ["", _("All")]
76
+
77
+ def choices(self, changelist: ChangeList) -> Generator[dict[str, Any], None, None]:
78
+ choices = [
79
+ self.all_option,
80
+ *[
81
+ ("1", _("Yes")),
82
+ ("0", _("No")),
83
+ ],
84
+ ]
85
+
86
+ yield {
87
+ "form": self.form_class(
88
+ label=_(" By %(filter_title)s ") % {"filter_title": self.title},
89
+ name=self.lookup_kwarg,
90
+ choices=choices,
91
+ data={self.lookup_kwarg: self.value()},
92
+ ),
93
+ }
94
+
95
+
96
+ class RelatedCheckboxFilter(MultiValueMixin, admin.RelatedFieldListFilter):
97
+ template = "unfold/filters/filters_field.html"
98
+ form_class = CheckboxForm
99
+
100
+ def queryset(self, request: HttpRequest, queryset: QuerySet) -> QuerySet:
101
+ if self.value() not in EMPTY_VALUES:
102
+ return super().queryset(request, queryset)
103
+
104
+ return queryset
105
+
106
+ def choices(self, changelist: ChangeList) -> Generator[dict[str, Any], None, None]:
107
+ yield {
108
+ "form": self.form_class(
109
+ label=_(" By %(filter_title)s ") % {"filter_title": self.title},
110
+ name=self.lookup_kwarg,
111
+ choices=self.lookup_choices,
112
+ data={self.lookup_kwarg: self.value()},
113
+ ),
114
+ }
115
+
116
+
117
+ class AllValuesCheckboxFilter(MultiValueMixin, admin.AllValuesFieldListFilter):
118
+ template = "unfold/filters/filters_field.html"
119
+ form_class = CheckboxForm
120
+
121
+ def choices(self, changelist: ChangeList) -> Generator[dict[str, Any], None, None]:
122
+ choices = [[i, val] for i, val in enumerate(self.lookup_choices)]
123
+
124
+ if len(choices) == 0:
125
+ return
126
+
127
+ yield {
128
+ "form": self.form_class(
129
+ label=_(" By %(filter_title)s ") % {"filter_title": self.title},
130
+ name=self.lookup_kwarg,
131
+ choices=[[i, val] for i, val in enumerate(self.lookup_choices)],
132
+ data={self.lookup_kwarg: self.value()},
133
+ ),
134
+ }
@@ -25,7 +25,7 @@ class DropdownFilter(admin.SimpleListFilter):
25
25
  return (
26
26
  {
27
27
  "form": self.form_class(
28
- label=_("By %(filter_title)s") % {"filter_title": self.title},
28
+ label=_(" By %(filter_title)s ") % {"filter_title": self.title},
29
29
  name=self.parameter_name,
30
30
  choices=[self.all_option, *self.lookup_choices],
31
31
  data={self.parameter_name: self.value()},
@@ -58,7 +58,7 @@ class ChoicesDropdownFilter(ValueMixin, DropdownMixin, admin.ChoicesFieldListFil
58
58
 
59
59
  yield {
60
60
  "form": self.form_class(
61
- label=_("By %(filter_title)s") % {"filter_title": self.title},
61
+ label=_(" By %(filter_title)s ") % {"filter_title": self.title},
62
62
  name=self.lookup_kwarg,
63
63
  choices=choices,
64
64
  data={self.lookup_kwarg: self.value()},
@@ -88,7 +88,7 @@ class RelatedDropdownFilter(ValueMixin, DropdownMixin, admin.RelatedFieldListFil
88
88
  def choices(self, changelist: ChangeList) -> Generator[dict[str, Any], None, None]:
89
89
  yield {
90
90
  "form": self.form_class(
91
- label=_("By %(filter_title)s") % {"filter_title": self.title},
91
+ label=_(" By %(filter_title)s ") % {"filter_title": self.title},
92
92
  name=self.lookup_kwarg,
93
93
  choices=[self.all_option, *self.lookup_choices],
94
94
  data={self.lookup_kwarg: self.value()},
@@ -141,7 +141,7 @@ class AutocompleteMixin:
141
141
  yield {
142
142
  "form": self.form_class(
143
143
  request=self.request,
144
- label=_("By %(filter_title)s") % {"filter_title": self.title},
144
+ label=_(" By %(filter_title)s ") % {"filter_title": self.title},
145
145
  name=self.lookup_kwarg,
146
146
  choices=(),
147
147
  field=self.field,
@@ -26,7 +26,7 @@ class TextFilter(admin.SimpleListFilter):
26
26
  {
27
27
  "form": self.form_class(
28
28
  name=self.parameter_name,
29
- label=_("By %(filter_title)s") % {"filter_title": self.title},
29
+ label=_(" By %(filter_title)s ") % {"filter_title": self.title},
30
30
  data={self.parameter_name: self.value()},
31
31
  ),
32
32
  },
@@ -57,7 +57,7 @@ class FieldTextFilter(ValueMixin, admin.FieldListFilter):
57
57
  return (
58
58
  {
59
59
  "form": self.form_class(
60
- label=_("By %(filter_title)s") % {"filter_title": self.title},
60
+ label=_(" By %(filter_title)s ") % {"filter_title": self.title},
61
61
  name=self.lookup_kwarg,
62
62
  data={self.lookup_kwarg: self.value()},
63
63
  ),
@@ -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 }}
@@ -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 }}
@@ -4,7 +4,7 @@
4
4
  {% with choices.0 as choice %}
5
5
  <div class="admin-numeric-filter-wrapper">
6
6
  <h3 class="font-semibold mb-2 text-font-important-light dark:text-font-important-dark">
7
- {% blocktrans with filter_title=title %}By {{ filter_title }}{% endblocktrans %}
7
+ {% blocktranslate with filter_title=title %} By {{ filter_title }} {% endblocktranslate %}
8
8
  </h3>
9
9
 
10
10
  {% if choice.min is not None and choice.max is not None and choice.step %}
unfold/decorators.py CHANGED
@@ -37,13 +37,19 @@ def action(
37
37
  # Permissions methods have following syntax: has_<some>_permission(self, request, obj=None):
38
38
  # But obj is not examined by default in django admin and it would also require additional
39
39
  # fetch from database, therefore it is not supported yet
40
- has_object_argument = (
41
- func.__name__ in model_admin.actions_detail
42
- or func.__name__ in model_admin.actions_submit_line
40
+ has_detail_action = func.__name__ in model_admin._extract_action_names(
41
+ model_admin.actions_detail
43
42
  )
43
+ has_submit_line_action = (
44
+ func.__name__
45
+ in model_admin._extract_action_names(
46
+ model_admin.actions_submit_line
47
+ )
48
+ )
49
+
44
50
  if not all(
45
51
  has_permission(request, kwargs.get("object_id"))
46
- if has_object_argument
52
+ if has_detail_action or has_submit_line_action
47
53
  else has_permission(request)
48
54
  for has_permission in permission_checks
49
55
  ):
unfold/forms.py CHANGED
@@ -50,8 +50,9 @@ class ActionForm(forms.Form):
50
50
  "pr-8",
51
51
  "rounded",
52
52
  "text-white",
53
+ "truncate",
53
54
  "*:text-base-700",
54
- "lg:min-w-72",
55
+ "lg:w-72",
55
56
  ]
56
57
  ),
57
58
  "aria-label": _("Select action to run"),
unfold/paginator.py ADDED
@@ -0,0 +1,10 @@
1
+ from django.core.paginator import Paginator
2
+ from django.utils.functional import cached_property
3
+
4
+
5
+ class InfinitePaginator(Paginator):
6
+ template_name = "unfold/helpers/pagination_infinite.html"
7
+
8
+ @cached_property
9
+ def count(self):
10
+ return 9_999_999_999
unfold/sites.py CHANGED
@@ -231,14 +231,16 @@ class UnfoldAdminSite(AdminSite):
231
231
  tabs = self._get_value(self._get_config("TABS", request), request) or []
232
232
  results = []
233
233
 
234
- for group in navigation:
234
+ for group in copy.deepcopy(navigation):
235
235
  allowed_items = []
236
236
 
237
237
  for item in group["items"]:
238
- item["active"] = False
239
- item["active"] = self._get_is_active(
240
- request, item.get("link_callback") or item["link"]
241
- )
238
+ if "active" in item:
239
+ item["active"] = self._get_value(item["active"], request)
240
+ else:
241
+ item["active"] = self._get_is_active(
242
+ request, item.get("link_callback") or item["link"]
243
+ )
242
244
 
243
245
  # Checks if any tab item is active and then marks the sidebar link as active
244
246
  for tab in tabs:
@@ -342,7 +344,7 @@ class UnfoldAdminSite(AdminSite):
342
344
  return target
343
345
 
344
346
  def _get_is_active(
345
- self, request: HttpRequest, link: str, is_tab: bool = False
347
+ self, request: HttpRequest, link: Union[str, Callable], is_tab: bool = False
346
348
  ) -> bool:
347
349
  if not isinstance(link, str):
348
350
  link = str(link)