django-unfold 0.67.0__py3-none-any.whl → 0.68.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {django_unfold-0.67.0.dist-info → django_unfold-0.68.0.dist-info}/METADATA +8 -5
- {django_unfold-0.67.0.dist-info → django_unfold-0.68.0.dist-info}/RECORD +39 -36
- unfold/admin.py +73 -13
- unfold/components.py +2 -2
- unfold/contrib/filters/admin/choice_filters.py +13 -1
- unfold/contrib/filters/admin/mixins.py +3 -3
- unfold/contrib/filters/admin/numeric_filters.py +6 -6
- unfold/contrib/forms/widgets.py +5 -5
- unfold/contrib/inlines/admin.py +3 -3
- unfold/contrib/inlines/forms.py +5 -4
- unfold/dataclasses.py +13 -13
- unfold/datasets.py +69 -0
- unfold/decorators.py +19 -19
- unfold/fields.py +3 -5
- unfold/forms.py +19 -7
- unfold/mixins/action_model_admin.py +11 -10
- unfold/mixins/base_model_admin.py +6 -6
- unfold/sites.py +14 -17
- unfold/static/unfold/css/styles.css +1 -1
- unfold/static/unfold/js/app.js +3 -1
- unfold/styles.css +21 -16
- unfold/templates/admin/change_form.html +5 -1
- unfold/templates/admin/change_list_results.html +10 -62
- unfold/templates/admin/edit_inline/stacked.html +1 -1
- unfold/templates/admin/search_form.html +5 -3
- unfold/templates/unfold/helpers/change_list_headers.html +65 -0
- unfold/templates/unfold/helpers/dataset.html +19 -0
- unfold/templates/unfold/helpers/edit_inline/tabular_field.html +1 -1
- unfold/templates/unfold/helpers/empty_results.html +6 -4
- unfold/templates/unfold/helpers/field_readonly_value_file.html +1 -1
- unfold/templates/unfold/helpers/tab_items.html +6 -0
- unfold/templatetags/unfold.py +18 -13
- unfold/templatetags/unfold_list.py +64 -8
- unfold/typing.py +5 -6
- unfold/utils.py +9 -9
- unfold/views.py +15 -1
- unfold/widgets.py +30 -29
- {django_unfold-0.67.0.dist-info → django_unfold-0.68.0.dist-info}/WHEEL +0 -0
- {django_unfold-0.67.0.dist-info → django_unfold-0.68.0.dist-info}/licenses/LICENSE.md +0 -0
@@ -1,11 +1,11 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: django-unfold
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.68.0
|
4
4
|
Summary: Modern Django admin theme for seamless interface development
|
5
5
|
License: MIT
|
6
6
|
License-File: LICENSE.md
|
7
7
|
Keywords: django,admin,tailwind,theme
|
8
|
-
Requires-Python: >=3.
|
8
|
+
Requires-Python: >=3.10,<4.0
|
9
9
|
Classifier: Environment :: Web Environment
|
10
10
|
Classifier: Framework :: Django
|
11
11
|
Classifier: Intended Audience :: Developers
|
@@ -13,7 +13,6 @@ Classifier: License :: OSI Approved :: MIT License
|
|
13
13
|
Classifier: Operating System :: OS Independent
|
14
14
|
Classifier: Programming Language :: Python
|
15
15
|
Classifier: Programming Language :: Python :: 3
|
16
|
-
Classifier: Programming Language :: Python :: 3.9
|
17
16
|
Classifier: Programming Language :: Python :: 3.10
|
18
17
|
Classifier: Programming Language :: Python :: 3.11
|
19
18
|
Classifier: Programming Language :: Python :: 3.12
|
@@ -24,7 +23,7 @@ Project-URL: Homepage, https://unfoldadmin.com
|
|
24
23
|
Project-URL: Repository, https://github.com/unfoldadmin/django-unfold
|
25
24
|
Description-Content-Type: text/markdown
|
26
25
|
|
27
|
-
](https://unfoldadmin.com)
|
28
27
|
|
29
28
|
## Unfold - Django Admin Theme
|
30
29
|
|
@@ -59,13 +58,16 @@ If you need assistance with integrating or customizing Unfold, support packages
|
|
59
58
|
|
60
59
|
Unfold Studio lets you visually customize your Django admin without writing code — update colors, logos, sidebar, and interface styles to match your brand in minutes. Give your admin a polished, professional look that feels truly yours. Available at [unfoldadmin.com/studio](https://unfoldadmin.com/studio).
|
61
60
|
|
61
|
+
[](https://unfoldadmin.com/studio)
|
62
|
+
|
63
|
+
|
62
64
|
## Fresh Features & Enhancements
|
63
65
|
|
66
|
+
- **Command**: Offers a command palette for quick searching across all models or custom-injected data
|
64
67
|
- **django-constance**: Official support with a completely new design and UX improvements
|
65
68
|
- **Paginated inlines:** Break down large record sets into pages within inlines for better admin performance
|
66
69
|
- **Conditional fields:** Show or hide fields dynamically based on the values of other fields in the form
|
67
70
|
- **Infinite paginator:** Efficiently handle large datasets with seamless pagination that reduces server load
|
68
|
-
- **Checkbox & radio filters:** Enhanced filter options with checkbox and radio interfaces for intuitive filtering
|
69
71
|
|
70
72
|
## Core Features & Capabilities
|
71
73
|
|
@@ -84,6 +86,7 @@ Unfold Studio lets you visually customize your Django admin without writing code
|
|
84
86
|
- **Model tabs:** Allow defining custom tab navigation for models
|
85
87
|
- **Fieldset tabs:** Merge multiple fieldsets into tabs in the change form
|
86
88
|
- **Sortable inlines:** Allow sorting inlines by dragging and dropping
|
89
|
+
- **Command**: Offers a command palette for quick searching across all models or custom-injected data
|
87
90
|
- **Environment label:** Distinguish between environments by displaying a label
|
88
91
|
- **Nonrelated inlines:** Display nonrelated models as inlines in the change form
|
89
92
|
- **Paginated inlines:** Break down large record sets into pages within inlines for better admin performance
|
@@ -1,8 +1,8 @@
|
|
1
1
|
unfold/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
unfold/admin.py,sha256=
|
2
|
+
unfold/admin.py,sha256=sLRfwfDy6rr9asgV4niufrg2ObMQ05VGBnmr33hStyo,9685
|
3
3
|
unfold/apps.py,sha256=SlBXPYrUd2uXn67qFbRvbXSUk3XFWrF4-5WELgDCvho,381
|
4
4
|
unfold/checks.py,sha256=e5HEhbXRcu3FwZDT_d-IbimeVpjJ6jgCUPXWvsUjEw0,2601
|
5
|
-
unfold/components.py,sha256=
|
5
|
+
unfold/components.py,sha256=E5sl0y3XDPSswHbRLVnJrdKNpZzZ-e5q4tLwMGACyZo,1270
|
6
6
|
unfold/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7
7
|
unfold/contrib/constance/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
8
8
|
unfold/contrib/constance/apps.py,sha256=636jGQ_C15fp5WRccmuSeZCZ4GOQ2PhXSEe4769uqrQ,139
|
@@ -12,11 +12,11 @@ unfold/contrib/constance/templates/admin/constance/includes/results_list.html,sh
|
|
12
12
|
unfold/contrib/filters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
13
|
unfold/contrib/filters/admin/__init__.py,sha256=7pooAoA2Y9MbBL_RTJBZeIAwV5ECrOvMbe0_egoHfew,1663
|
14
14
|
unfold/contrib/filters/admin/autocomplete_filters.py,sha256=Jh3m3iQ8YubZRQDVzHPGfpk9RulOhHkZc0N7L6KV9wc,514
|
15
|
-
unfold/contrib/filters/admin/choice_filters.py,sha256=
|
15
|
+
unfold/contrib/filters/admin/choice_filters.py,sha256=_IoZaPlcpFLlr7j09lcJ6ALb4olShzKF8rJWKNKJMzo,6010
|
16
16
|
unfold/contrib/filters/admin/datetime_filters.py,sha256=cVari_7jsfeYxJoRBhcAUOr6v9XdtDtMuMs-S1Irafo,7757
|
17
17
|
unfold/contrib/filters/admin/dropdown_filters.py,sha256=exiIyU6c_as7XBJsaAPPx5b8eY3IDbuCFGPJu1b0ux4,3856
|
18
|
-
unfold/contrib/filters/admin/mixins.py,sha256=
|
19
|
-
unfold/contrib/filters/admin/numeric_filters.py,sha256=
|
18
|
+
unfold/contrib/filters/admin/mixins.py,sha256=A0G4pwmpaEg4VHk6fBXHHtiancpsJl9JsQSefmMLZso,5823
|
19
|
+
unfold/contrib/filters/admin/numeric_filters.py,sha256=dRjerPcdKb0yMrdCDR_zOSzju3s9-1RCBshg1654r2U,6475
|
20
20
|
unfold/contrib/filters/admin/text_filters.py,sha256=19cOEGpSaXafcM8QuGiYaWmNi5UIQnCXEhKG-vCTfe8,2088
|
21
21
|
unfold/contrib/filters/apps.py,sha256=wEySJy0gMLzFLb9XNKE-RexiO05X7NaQ5QmxZyziJ_k,136
|
22
22
|
unfold/contrib/filters/forms.py,sha256=cebAmMPKtofdwvUhAVaoP5V3rNhwYe0Df5k06TJwZfo,8560
|
@@ -44,7 +44,7 @@ unfold/contrib/forms/static/unfold/forms/js/trix.config.js,sha256=spkNBlJVk_pqid
|
|
44
44
|
unfold/contrib/forms/templates/unfold/forms/array.html,sha256=EKN_Tk1YKrdhZfOcC9aMKZMKyIiBk9frF0tYDWXqiDA,1799
|
45
45
|
unfold/contrib/forms/templates/unfold/forms/helpers/toolbar.html,sha256=_sPtxaK14XzdfB6sAwA7ZYHbfIMtaKbORByxjxXoNh8,10130
|
46
46
|
unfold/contrib/forms/templates/unfold/forms/wysiwyg.html,sha256=uLLf59jsD3apAm9Uh1TH4pwCOtO7pL2djAeZLOHyNAI,399
|
47
|
-
unfold/contrib/forms/widgets.py,sha256=
|
47
|
+
unfold/contrib/forms/widgets.py,sha256=qjQ7al5CTVpBhsvTVr-6dTplJHB4dWeMxgh1tjU7Crc,3356
|
48
48
|
unfold/contrib/guardian/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
49
49
|
unfold/contrib/guardian/apps.py,sha256=ObJqwh4vHxkD4XfduP5IQAiYiWZxsXUOUqF1_R1GsRI,136
|
50
50
|
unfold/contrib/guardian/templates/admin/guardian/model/change_form.html,sha256=FSJc4MYYWyzZAy8Ay0b7Ov-cUo-oELHOM5fQehM54Lg,403
|
@@ -73,10 +73,10 @@ unfold/contrib/import_export/templates/admin/import_export/import_preview.html,s
|
|
73
73
|
unfold/contrib/import_export/templates/admin/import_export/import_validation.html,sha256=K7j5OlWMQUTcSVulJtIraKfWIupSvmN4R5bZ2hH4tRA,5117
|
74
74
|
unfold/contrib/import_export/templates/admin/import_export/resource_fields_list.html,sha256=Bc6uD8aHA5YYbZgLAPpGUckFjnxn9uq19YuKKFxTj4Y,887
|
75
75
|
unfold/contrib/inlines/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
76
|
-
unfold/contrib/inlines/admin.py,sha256=
|
76
|
+
unfold/contrib/inlines/admin.py,sha256=7KNC1vikoOcpIwFu6oc1UvaS7u02VsnRypF5Z7qno9I,6050
|
77
77
|
unfold/contrib/inlines/apps.py,sha256=Z9JBnzywq-DanZbD56fG0ndBfLXbojzkjVBleqoOBSU,136
|
78
78
|
unfold/contrib/inlines/checks.py,sha256=0vkHUh-MtNSTrcOjCLbZmtI4961fFOygOv_dBAps6zw,534
|
79
|
-
unfold/contrib/inlines/forms.py,sha256=
|
79
|
+
unfold/contrib/inlines/forms.py,sha256=yqhYxiNfcjMwMrNrCpN7wCnJtZytwt90jmPNfV_WWP0,1403
|
80
80
|
unfold/contrib/location_field/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
81
81
|
unfold/contrib/location_field/apps.py,sha256=qbNLfWXWf9q_gZxnuwFNVj20liSk_OT29uWMAi1she8,150
|
82
82
|
unfold/contrib/location_field/templates/location_field/map_widget.html,sha256=vIBWNxIiCZipMnnPkZBFEZa-F3qXTKz9t4DbMmiBSSM,184
|
@@ -86,26 +86,27 @@ unfold/contrib/simple_history/templates/simple_history/object_history.html,sha25
|
|
86
86
|
unfold/contrib/simple_history/templates/simple_history/object_history_form.html,sha256=TuQ_Fwrefjo3p9A-2asBxVq9bRJ9j5r11Jy-uS7K0TU,751
|
87
87
|
unfold/contrib/simple_history/templates/simple_history/object_history_list.html,sha256=kMtxD5II32etsk05IArxe_wGvVjrizMVVH8uRl5RjR0,6816
|
88
88
|
unfold/contrib/simple_history/templates/simple_history/submit_line.html,sha256=PEoPmWcWiiBIMs6XtXcoXswDtxp3FgntR3maieLDt4Y,1618
|
89
|
-
unfold/dataclasses.py,sha256=
|
90
|
-
unfold/
|
89
|
+
unfold/dataclasses.py,sha256=nCzcUufg60HHlJcAAgfSI_YPjXil3s2uMMhlJI0Lidk,803
|
90
|
+
unfold/datasets.py,sha256=ufWFJylqOiSJX2CYlQC8SpkAv2q84Fn63RvSkPdzIFc,2106
|
91
|
+
unfold/decorators.py,sha256=WWDhYipXs-z9ppyAteC9HVWJGvv8B-gIigrTF6hj4KM,4844
|
91
92
|
unfold/enums.py,sha256=9sTfyEycMWeoGPBa-ft6ZhQGnW1vkFg108RMBVf9nko,187
|
92
93
|
unfold/exceptions.py,sha256=gcCj1ox61E137bk_0Cqy4YC3SttdPgB-fiJUqpmyHSE,43
|
93
|
-
unfold/fields.py,sha256=
|
94
|
-
unfold/forms.py,sha256=
|
94
|
+
unfold/fields.py,sha256=883cbZFen5Ss8OKxAVrIbFynYn4em3TkWkyCksMcPWo,8344
|
95
|
+
unfold/forms.py,sha256=HE4F_WqVgywk1u5J54WP94yeGGFuGxK6UrIsxtB-9k4,8133
|
95
96
|
unfold/layout.py,sha256=Q-dFTA6UlvvPCA4PsGyTkHQmBLO7PL56xBfZi-bdt0c,1459
|
96
97
|
unfold/mixins/__init__.py,sha256=YlhoDs9Y_DXQ8Ejr3enxuHMS1-Ij9fwukxNwpeOS4Co,190
|
97
|
-
unfold/mixins/action_model_admin.py,sha256=
|
98
|
-
unfold/mixins/base_model_admin.py,sha256=
|
98
|
+
unfold/mixins/action_model_admin.py,sha256=h5z1ZqjIdqzSbe-pTrV8Yrw7ipp1OXATLXMjBe9Q6Hk,12332
|
99
|
+
unfold/mixins/base_model_admin.py,sha256=rAZspMkeESgSsbyFpubCr4gDbi7SopvT6--stRhqGRI,4777
|
99
100
|
unfold/overrides.py,sha256=ERVY9boZiXgjDYcTEZcIp7KWoeBZ45VM_zN31yAOjyQ,2922
|
100
101
|
unfold/paginator.py,sha256=bZiEY-1kqZy_6CYGs9fHo6WntMgpnFCH-LJPoXkEESk,533
|
101
102
|
unfold/sections.py,sha256=Lcg3xCZ76fqjm4vD4x7YdE5VsbTKluL-sX5QTEBlHxA,2379
|
102
103
|
unfold/settings.py,sha256=o_yjhM1OgW2KSrae4oeUqjLw3lI9HZ1lkKGUW4nuC4Q,3432
|
103
|
-
unfold/sites.py,sha256=
|
104
|
+
unfold/sites.py,sha256=qDdUBX6Q0TYSNQXovn7h9vuCZXopX8v_4vmxYbs_4t0,21314
|
104
105
|
unfold/static/admin/js/admin/RelatedObjectLookups.js,sha256=ubKKhWmX_QborwPnaLHuQshTwQw6tK1pAViWdKIjw4E,9222
|
105
106
|
unfold/static/admin/js/inlines.js,sha256=UXtFzCWHZWIJbxRghlNsNsz8HuRHjcaH1Mvb5e6uJms,16222
|
106
107
|
unfold/static/unfold/css/simplebar/LICENSE,sha256=okNJf6UFl2NrEiC4iqORNBa16IKgUgV88acdcl9FbtY,1081
|
107
108
|
unfold/static/unfold/css/simplebar/simplebar.css,sha256=5LLaEM11pKi6JFCOLt4XKuZxTpT9rpdq_tNlaQytFlU,4647
|
108
|
-
unfold/static/unfold/css/styles.css,sha256=
|
109
|
+
unfold/static/unfold/css/styles.css,sha256=H22ldb2tEY0zCuTISs3_gNmt2k37erO5XAXFkiGWPRM,211578
|
109
110
|
unfold/static/unfold/fonts/inter/Inter-Bold.woff2,sha256=-oiBJ7baAVtlVp8DUfO1w5GtkokElR8cIOn4RiqNleo,114840
|
110
111
|
unfold/static/unfold/fonts/inter/Inter-Medium.woff2,sha256=D_PpRhThST61VjFP0keubEqFp3g7TMhr5TmUDPg_Kkg,114348
|
111
112
|
unfold/static/unfold/fonts/inter/Inter-Regular.woff2,sha256=4G9rG8VTqupORmgCPtCrChRxKcMQf1Ebx9A9NhsK4IU,111268
|
@@ -121,7 +122,7 @@ unfold/static/unfold/js/alpine/alpine.js,sha256=PtHu0lJIiSHfZeNj1nFd6wTX-Squ255S
|
|
121
122
|
unfold/static/unfold/js/alpine/alpine.persist.js,sha256=jFBwr6faTqqhp3sVi4_VTxJ0FpaF9YGZN1ZGLl_5QYM,837
|
122
123
|
unfold/static/unfold/js/alpine/alpine.resize.js,sha256=mXR2L6neT584cfNLY5_imDq5DKjW1noXys7fhb1yxY4,703
|
123
124
|
unfold/static/unfold/js/alpine/alpine.sort.js,sha256=q6LxgConwu8M8R03mZSBcsKwJv6fF7oomP8sqLxVQ0w,37891
|
124
|
-
unfold/static/unfold/js/app.js,sha256=
|
125
|
+
unfold/static/unfold/js/app.js,sha256=GW-kAIuEW56h0Eaws0opoK1Ck-eTVjnj5hcbwzeZxIA,16352
|
125
126
|
unfold/static/unfold/js/chart/LICENSE,sha256=QahKosq6ZF-WahjZwgVrc-bTqB2AvABGvAARomNNTM4,1093
|
126
127
|
unfold/static/unfold/js/chart/chart.js,sha256=22W6cFERR-CElMOKRgMMicueMVP0Vf7FBEBYH8Z8tCk,200633
|
127
128
|
unfold/static/unfold/js/htmx/LICENSE,sha256=09JFb3ZBTyRWEEZg69Za_xwEzXlmuUK9q9Y_PNsxajg,642
|
@@ -129,7 +130,7 @@ unfold/static/unfold/js/htmx/htmx.js,sha256=acrv0NqSJpBm5yXX_hdeJrnVDJYuMFZFnAxH
|
|
129
130
|
unfold/static/unfold/js/select2.init.js,sha256=SeUUXgwLi26Tmh1Sgl3al4WeqlvmbZgixmTtwhJMMq0,1009
|
130
131
|
unfold/static/unfold/js/simplebar/LICENSE,sha256=okNJf6UFl2NrEiC4iqORNBa16IKgUgV88acdcl9FbtY,1081
|
131
132
|
unfold/static/unfold/js/simplebar/simplebar.js,sha256=t-uG1FAD6ZoiMeN--wac0XRS7SxoDVG6zvRnGuEp7X8,27176
|
132
|
-
unfold/styles.css,sha256=
|
133
|
+
unfold/styles.css,sha256=4GfTn3K3y-X1xa6w2V6489XqmsxTSOwqtrKlCEaRE6c,21527
|
133
134
|
unfold/templates/admin/actions.html,sha256=iuuubcAILkOoYBgV6cpXqFIyZUh4zMqyFp0JaDFlPKU,3096
|
134
135
|
unfold/templates/admin/app_index.html,sha256=hcXcaEwqKYTaClnGzlBEsTzy3YJn_37AiFs4YVbvX8A,585
|
135
136
|
unfold/templates/admin/app_list.html,sha256=-DEZKFdmkdTq3rix_cgZurPZ1r8PHg5pBL3i7ZtzVdI,2972
|
@@ -137,15 +138,15 @@ unfold/templates/admin/auth/user/add_form.html,sha256=-_YY4guGdAbw2rCskrQfRAAvQF
|
|
137
138
|
unfold/templates/admin/auth/user/change_password.html,sha256=3NIopJ8JFN4iv428kUTqRthZvmden9sb0-D7AKohRjA,1577
|
138
139
|
unfold/templates/admin/base.html,sha256=CuttiTMMtEiPNIEv4VXt27UGITgqPZaz5V8BJlBEOdk,1663
|
139
140
|
unfold/templates/admin/base_site.html,sha256=UOsecaCycpyn_ygJNIKO7MQtDFJuHv--r83-mzaVY30,300
|
140
|
-
unfold/templates/admin/change_form.html,sha256=
|
141
|
+
unfold/templates/admin/change_form.html,sha256=GSDucoXPJdGjuG9ji8fM3CJhW0bTtDhZ18hKxAgIZpM,4876
|
141
142
|
unfold/templates/admin/change_form_object_tools.html,sha256=eyeH-i2HgEM0Yi-OJA2D1VnKJyC19A_my1IDGxxoP8Y,593
|
142
143
|
unfold/templates/admin/change_list.html,sha256=aesNLu_b4j90Q08nWpMlVembYuH0TMGhwO7DJMMrSsI,4503
|
143
144
|
unfold/templates/admin/change_list_object_tools.html,sha256=cmMiT2nT20Ph5yfpj9aHPr76Z-JP4aSXp0o-Rnad28s,147
|
144
|
-
unfold/templates/admin/change_list_results.html,sha256=
|
145
|
+
unfold/templates/admin/change_list_results.html,sha256=G4OJb7Quqc5qQeWT0zl6kN-BzUVaOtN2nYoiPdrUS_w,5069
|
145
146
|
unfold/templates/admin/date_hierarchy.html,sha256=A-sIqBKzZTMqSn3NSHORIL1yTEAqhj4Atff0OvWtqT0,1413
|
146
147
|
unfold/templates/admin/delete_confirmation.html,sha256=0vHhrbUAOW8CXfkEB20JoA9qV5xRbyb5xGc1jpWcrN4,3661
|
147
148
|
unfold/templates/admin/delete_selected_confirmation.html,sha256=mtRZyZH5xBRk60KktA8PZviAeI3yOH34cS_FDHaZOu0,3401
|
148
|
-
unfold/templates/admin/edit_inline/stacked.html,sha256=
|
149
|
+
unfold/templates/admin/edit_inline/stacked.html,sha256=TcYSqEiuFWvwbse1ehVDVQD2vIRaLJtzb0jIKFzdQJ0,8625
|
149
150
|
unfold/templates/admin/edit_inline/tabular.html,sha256=DtXaKC_0HEKPIphbqiykixQa1cRrEYcnLV7I3VlynhU,3020
|
150
151
|
unfold/templates/admin/filter.html,sha256=DEyrLgCWuncS1O1WR0vlt1evGQFvKoZV2pABkHzSoGU,2039
|
151
152
|
unfold/templates/admin/includes/fieldset.html,sha256=UWcatsmHzfdcjZP58P94YL7BI3F-CP-BgYi2uC7FSb4,1471
|
@@ -155,7 +156,7 @@ unfold/templates/admin/login.html,sha256=E963dlzjZlkNc6WPJg9DiqijWAhRp1QLVCxFHkR
|
|
155
156
|
unfold/templates/admin/nav_sidebar.html,sha256=NiNcLF-0eZwwv2arsikChzwbH7FTI1vEch427KddFlk,772
|
156
157
|
unfold/templates/admin/object_history.html,sha256=4S9xpBtywUdFPUmvAuH2lMOG6jxCFZ-rFZYnhbajkRw,3726
|
157
158
|
unfold/templates/admin/pagination.html,sha256=-9kjc_lKEeqvDVHMrnTfnlXDxMSkM8GNRGZGuI9D8os,912
|
158
|
-
unfold/templates/admin/search_form.html,sha256=
|
159
|
+
unfold/templates/admin/search_form.html,sha256=bo0WXtAZZi1uw-D1UDQ_Q0mUt8z5FDEEwseShdngN48,1862
|
159
160
|
unfold/templates/admin/submit_line.html,sha256=9FDZ5HOfiJG11HSMtA4rfqjKe3ucC-_OChpx1CGTLac,4626
|
160
161
|
unfold/templates/auth/widgets/read_only_password_hash.html,sha256=MlaNXJ2PLEbv8Nd01BBp-AQEfMB13LNxD_DzRemXhCg,775
|
161
162
|
unfold/templates/registration/logged_out.html,sha256=ytjIz3abnpERwUp1F8zn89HyrimSrb9wgUna3Iz0CJE,1202
|
@@ -188,24 +189,26 @@ unfold/templates/unfold/helpers/breadcrumb_item.html,sha256=9T6ojN7LOXIlgwSwlIwH
|
|
188
189
|
unfold/templates/unfold/helpers/change_list_actions.html,sha256=xuFMZel6kH014H9sl0hKvQo7LP0UxwlhFQHIUeyQxVM,643
|
189
190
|
unfold/templates/unfold/helpers/change_list_filter.html,sha256=WwU-AG4U5qZQ_sFs1z_jaaYBWqIv3ASmtKIQIhAp2gs,1908
|
190
191
|
unfold/templates/unfold/helpers/change_list_filter_actions.html,sha256=K99hHgpCLaAHxv-eqIf4nOUfq6CeTQHekEeudKTRYME,2036
|
192
|
+
unfold/templates/unfold/helpers/change_list_headers.html,sha256=_pGLbrTuzmlowfydbCEjbKCqCf3z6juhGxMdb8l9j0M,3545
|
191
193
|
unfold/templates/unfold/helpers/command.html,sha256=VDy7b6mlDL9kpt2VrCuUQwzjwUOPztUL3hrU2kp0tVs,2885
|
192
194
|
unfold/templates/unfold/helpers/command_history.html,sha256=AB5elGPyY51aHuaWnwXddZmdcSadcqBOzdzjYqR4lfU,2866
|
193
195
|
unfold/templates/unfold/helpers/command_results.html,sha256=3sYaBePPt9o_WDS9UeZojW-QZzbOGd474r2Elfn_33Q,3679
|
196
|
+
unfold/templates/unfold/helpers/dataset.html,sha256=mweBoXLW2vpMiJvwEGedXsOc4OdEBsr_O9f15zSgvWY,784
|
194
197
|
unfold/templates/unfold/helpers/delete_submit_line.html,sha256=7SNS0axGytvUih9KxtOzy9ZC5rwG9u99iQxlnUZQfdE,700
|
195
198
|
unfold/templates/unfold/helpers/display_dropdown.html,sha256=IpOy8-hww4arAVjPIRsHrip30J3IEd2p-2BzD3BjIaA,2906
|
196
199
|
unfold/templates/unfold/helpers/display_header.html,sha256=2u-5Vc3mA6rS3ZlOWm3WRNLUX1wmZy4OSmGY2mdPZYs,1714
|
197
200
|
unfold/templates/unfold/helpers/display_label.html,sha256=LS9DWzYjHkYLV27sZDwyXlg2sLJ0AlId9FbjnXpsbfg,317
|
198
201
|
unfold/templates/unfold/helpers/edit_inline/tabular_delete.html,sha256=wr8zmSUhKcoxxms6gJsBqBrANFTOXELYUvlr3XjnjnE,931
|
199
202
|
unfold/templates/unfold/helpers/edit_inline/tabular_error.html,sha256=8XGlgUJ47JllmXhwPZDlcl81NzZmvuBIp8FZBWoeu9Q,336
|
200
|
-
unfold/templates/unfold/helpers/edit_inline/tabular_field.html,sha256=
|
203
|
+
unfold/templates/unfold/helpers/edit_inline/tabular_field.html,sha256=xw4Mrxf6AirZcOyLeg5sRjlHBftWlCOE-_A9F-OEdEo,1004
|
201
204
|
unfold/templates/unfold/helpers/edit_inline/tabular_heading.html,sha256=wvnpGFJVHFvamGLpRCpGoP7WALFKqR1KKvVIIRhWFQc,1520
|
202
205
|
unfold/templates/unfold/helpers/edit_inline/tabular_row.html,sha256=eCyWEYvvDDCr9SR4_0ua5-GqCLIlFzgQYIZP0ip8cp8,2145
|
203
206
|
unfold/templates/unfold/helpers/edit_inline/tabular_title.html,sha256=2sk1TRzpmwy8PPPMNdf6CJx0zVSk-I2q3yX8uEPjuxE,2710
|
204
|
-
unfold/templates/unfold/helpers/empty_results.html,sha256=
|
207
|
+
unfold/templates/unfold/helpers/empty_results.html,sha256=X0cno3qZ2nbiRQSMjH1zB97Z_nSVM7M0EOOGV6mx734,2117
|
205
208
|
unfold/templates/unfold/helpers/field.html,sha256=KEs1SQRxzJ0x11zithlxVyv5zfQ9a_XGoJJ9AiWk1Vc,1038
|
206
209
|
unfold/templates/unfold/helpers/field_readonly.html,sha256=4qtXjWE7SA2qZSTYLOv0lT4pQfD0TE34mvWQJY7jhS8,237
|
207
210
|
unfold/templates/unfold/helpers/field_readonly_value.html,sha256=dQHLb3eWeTZnXVzT8vaCbFNb4H9NwwNAv3qOKpOfDtM,531
|
208
|
-
unfold/templates/unfold/helpers/field_readonly_value_file.html,sha256=
|
211
|
+
unfold/templates/unfold/helpers/field_readonly_value_file.html,sha256=1oHAVkn71WbVxKTjwQMyW03yIZBbKY-ZSorZA5wlrgI,710
|
209
212
|
unfold/templates/unfold/helpers/fieldset_row.html,sha256=LriorPLXU4VmqstjX1oBc3T49H8CbhCrRxwQ7YfUSkI,1219
|
210
213
|
unfold/templates/unfold/helpers/fieldset_row_checkbox.html,sha256=z4aRab--zJS2PC0jfKPez85IptKGRrqgkPpwW6_IKoo,1467
|
211
214
|
unfold/templates/unfold/helpers/fieldset_row_field.html,sha256=cqLT1fHsCCszOHxvYlDFDTAd-6RRoOjdqfdBdhFgHOo,647
|
@@ -246,7 +249,7 @@ unfold/templates/unfold/helpers/site_logo.html,sha256=S_QJoT2qh0xw0ciaKxoT4GJ6QI
|
|
246
249
|
unfold/templates/unfold/helpers/submit.html,sha256=6bfZ7V2PTJfSXGg4K3IEZ42oREkMdAVjfP8yaM8Tu0k,226
|
247
250
|
unfold/templates/unfold/helpers/tab_action.html,sha256=mJd87_2qkSNQEwDZZCDkvll5ZbizBkPxWFnBR-kH89o,3431
|
248
251
|
unfold/templates/unfold/helpers/tab_actions.html,sha256=koe4D-vm7PRPqZ4FPjo3KEfWARebcpt1KuUJ7oa7PK4,685
|
249
|
-
unfold/templates/unfold/helpers/tab_items.html,sha256=
|
252
|
+
unfold/templates/unfold/helpers/tab_items.html,sha256=VNdzOnjH-vCIhgnyqIXyu3S8p91i_qLRKez3BwX5LZQ,2297
|
250
253
|
unfold/templates/unfold/helpers/tab_list.html,sha256=7Jy4QrGfmKq4ORBi9w_Wya_b2QJZOZndvILDaM1unBc,386
|
251
254
|
unfold/templates/unfold/helpers/theme_switch.html,sha256=Y46KKpULH_G-fKQuc5LzfSB7Pubcgj_dBJPRMwZoWxE,2408
|
252
255
|
unfold/templates/unfold/helpers/unauthenticated_header.html,sha256=nBTHKonEmR87zMAivl48E4c1xOVcTujodn6H9rAf_6U,601
|
@@ -299,13 +302,13 @@ unfold/templates/unfold_crispy/uni_form.html,sha256=l9UNCUrIycgJ0p_B6qhtO_YxdARy
|
|
299
302
|
unfold/templates/unfold_crispy/whole_uni_form.html,sha256=ufXRKCIGqkqKFOsh166rpKUnHpFMyBV4eYUCRhs3iws,475
|
300
303
|
unfold/templates/unfold_crispy/whole_uni_formset.html,sha256=CYksfG2hRUdi5n691KW2ih-FfBxpOU4qVBfbOvcu1zs,873
|
301
304
|
unfold/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
302
|
-
unfold/templatetags/unfold.py,sha256=
|
303
|
-
unfold/templatetags/unfold_list.py,sha256=
|
304
|
-
unfold/typing.py,sha256=
|
305
|
-
unfold/utils.py,sha256=
|
306
|
-
unfold/views.py,sha256=
|
307
|
-
unfold/widgets.py,sha256=
|
308
|
-
django_unfold-0.
|
309
|
-
django_unfold-0.
|
310
|
-
django_unfold-0.
|
311
|
-
django_unfold-0.
|
305
|
+
unfold/templatetags/unfold.py,sha256=j50CfXpT-Mq9_ggvmvXhZiTiDnkuRgzat4bZoRpB2HI,24575
|
306
|
+
unfold/templatetags/unfold_list.py,sha256=ld95N81rIjPyZ2DsDQXpoiFQ0YQ8zbqIMYRCtrGBuLQ,16096
|
307
|
+
unfold/typing.py,sha256=N3W54YqV2Kig0y3sP2gHKM4ZuHxpzYe2L9J4ve9rnPg,651
|
308
|
+
unfold/utils.py,sha256=qNwL3Wsv3u8nzB5l9PXAXRp6w4p4qXDbQHJAScbXSy4,6804
|
309
|
+
unfold/views.py,sha256=4hnLureeD-5xVABO-EDFPoGHpmtOgAuyB7cE4QLkfos,2255
|
310
|
+
unfold/widgets.py,sha256=q29qq7mC32DHZ7DxXd7Fo_nOFFDtdpRBeY7TsQA067I,24659
|
311
|
+
django_unfold-0.68.0.dist-info/METADATA,sha256=1dQ37Cyg2ucjwCuN43SbMm9Y0Esa1lHjcdcL3nBykoQ,10277
|
312
|
+
django_unfold-0.68.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
313
|
+
django_unfold-0.68.0.dist-info/licenses/LICENSE.md,sha256=Ltk_quRyyvV3J5v3brtOqmibeZSw2Hrb8bY1W3ya0Ik,1077
|
314
|
+
django_unfold-0.68.0.dist-info/RECORD,,
|
unfold/admin.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
from functools import update_wrapper
|
2
|
-
from typing import Any
|
2
|
+
from typing import Any
|
3
3
|
|
4
4
|
from django import forms
|
5
5
|
from django.contrib.admin import ModelAdmin as BaseModelAdmin
|
@@ -7,6 +7,8 @@ from django.contrib.admin import StackedInline as BaseStackedInline
|
|
7
7
|
from django.contrib.admin import TabularInline as BaseTabularInline
|
8
8
|
from django.contrib.admin import display, helpers
|
9
9
|
from django.contrib.admin.options import InlineModelAdmin
|
10
|
+
from django.contrib.admin.views import main
|
11
|
+
from django.contrib.admin.views.main import IGNORED_PARAMS
|
10
12
|
from django.contrib.contenttypes.admin import (
|
11
13
|
GenericStackedInline as BaseGenericStackedInline,
|
12
14
|
)
|
@@ -23,6 +25,7 @@ from django.utils.translation import gettext_lazy as _
|
|
23
25
|
from django.views import View
|
24
26
|
|
25
27
|
from unfold.checks import UnfoldModelAdminChecks
|
28
|
+
from unfold.datasets import BaseDataset
|
26
29
|
from unfold.forms import (
|
27
30
|
ActionForm,
|
28
31
|
PaginationGenericInlineFormSet,
|
@@ -47,6 +50,8 @@ class ModelAdmin(BaseModelAdminMixin, ActionModelAdminMixin, BaseModelAdmin):
|
|
47
50
|
action_form = ActionForm
|
48
51
|
custom_urls = ()
|
49
52
|
add_fieldsets = ()
|
53
|
+
ordering_field = None
|
54
|
+
hide_ordering_field = False
|
50
55
|
list_horizontal_scrollbar_top = False
|
51
56
|
list_filter_submit = False
|
52
57
|
list_filter_sheet = True
|
@@ -58,6 +63,7 @@ class ModelAdmin(BaseModelAdminMixin, ActionModelAdminMixin, BaseModelAdmin):
|
|
58
63
|
change_form_after_template = None
|
59
64
|
change_form_outer_before_template = None
|
60
65
|
change_form_outer_after_template = None
|
66
|
+
change_form_datasets = ()
|
61
67
|
compressed_fields = False
|
62
68
|
readonly_preprocess_fields = {}
|
63
69
|
warn_unsaved_form = False
|
@@ -72,7 +78,7 @@ class ModelAdmin(BaseModelAdminMixin, ActionModelAdminMixin, BaseModelAdmin):
|
|
72
78
|
|
73
79
|
for filter in self.get_list_filter(self.request):
|
74
80
|
if (
|
75
|
-
isinstance(filter,
|
81
|
+
isinstance(filter, tuple | list)
|
76
82
|
and hasattr(filter[1], "form_class")
|
77
83
|
and hasattr(filter[1].form_class, "Media")
|
78
84
|
):
|
@@ -83,12 +89,61 @@ class ModelAdmin(BaseModelAdminMixin, ActionModelAdminMixin, BaseModelAdmin):
|
|
83
89
|
return media
|
84
90
|
|
85
91
|
def changelist_view(
|
86
|
-
self, request: HttpRequest, extra_context:
|
92
|
+
self, request: HttpRequest, extra_context: dict[str, str] | None = None
|
87
93
|
) -> TemplateResponse:
|
88
94
|
self.request = request
|
95
|
+
|
96
|
+
if self.ordering_field and self.ordering_field not in self.list_editable:
|
97
|
+
list_editable = list(getattr(self, "list_editable", []))
|
98
|
+
list_editable.append(self.ordering_field)
|
99
|
+
self.list_editable = list_editable
|
100
|
+
|
89
101
|
return super().changelist_view(request, extra_context)
|
90
102
|
|
91
|
-
def
|
103
|
+
def changeform_view(
|
104
|
+
self,
|
105
|
+
request: HttpRequest,
|
106
|
+
object_id: str | None = None,
|
107
|
+
form_url: str = "",
|
108
|
+
extra_context: dict[str, Any] | None = None,
|
109
|
+
) -> TemplateResponse:
|
110
|
+
self.request = request
|
111
|
+
extra_context = extra_context or {}
|
112
|
+
datasets = self.get_changeform_datasets(request)
|
113
|
+
|
114
|
+
# Monkeypatch IGNORED_PARAMS to add dataset page and search arguments into ignored params
|
115
|
+
ignored_params = []
|
116
|
+
for dataset in datasets:
|
117
|
+
ignored_params.append(f"{dataset.model._meta.model_name}-q")
|
118
|
+
ignored_params.append(f"{dataset.model._meta.model_name}-p")
|
119
|
+
|
120
|
+
main.IGNORED_PARAMS = (*IGNORED_PARAMS, *ignored_params)
|
121
|
+
|
122
|
+
rendered_datasets = []
|
123
|
+
for dataset in datasets:
|
124
|
+
rendered_datasets.append(
|
125
|
+
dataset(
|
126
|
+
request=request,
|
127
|
+
extra_context={
|
128
|
+
"object": object_id,
|
129
|
+
},
|
130
|
+
)
|
131
|
+
)
|
132
|
+
|
133
|
+
extra_context["datasets"] = rendered_datasets
|
134
|
+
return super().changeform_view(request, object_id, form_url, extra_context)
|
135
|
+
|
136
|
+
def get_list_display(self, request: HttpRequest) -> list[str]:
|
137
|
+
list_display = super().get_list_display(request)
|
138
|
+
|
139
|
+
if self.ordering_field and self.ordering_field not in list_display:
|
140
|
+
list_display.append(self.ordering_field)
|
141
|
+
|
142
|
+
return list_display
|
143
|
+
|
144
|
+
def get_fieldsets(
|
145
|
+
self, request: HttpRequest, obj: Model | None = None
|
146
|
+
) -> FieldsetsType:
|
92
147
|
if not obj and self.add_fieldsets:
|
93
148
|
return self.add_fieldsets
|
94
149
|
return super().get_fieldsets(request, obj)
|
@@ -119,7 +174,7 @@ class ModelAdmin(BaseModelAdminMixin, ActionModelAdminMixin, BaseModelAdmin):
|
|
119
174
|
|
120
175
|
actions_list_urls = [
|
121
176
|
path(
|
122
|
-
action.path,
|
177
|
+
f"{action.path.removesuffix('/')}/",
|
123
178
|
wrap(action.method),
|
124
179
|
name=action.action_name,
|
125
180
|
)
|
@@ -128,7 +183,7 @@ class ModelAdmin(BaseModelAdminMixin, ActionModelAdminMixin, BaseModelAdmin):
|
|
128
183
|
|
129
184
|
action_detail_urls = [
|
130
185
|
path(
|
131
|
-
f"<path:object_id>/{action.path}",
|
186
|
+
f"<path:object_id>/{action.path.removesuffix('/')}/",
|
132
187
|
wrap(action.method),
|
133
188
|
name=action.action_name,
|
134
189
|
)
|
@@ -137,7 +192,7 @@ class ModelAdmin(BaseModelAdminMixin, ActionModelAdminMixin, BaseModelAdmin):
|
|
137
192
|
|
138
193
|
action_row_urls = [
|
139
194
|
path(
|
140
|
-
f"<path:object_id>/{action.path}",
|
195
|
+
f"<path:object_id>/{action.path.removesuffix('/')}/",
|
141
196
|
wrap(action.method),
|
142
197
|
name=action.action_name,
|
143
198
|
)
|
@@ -152,7 +207,7 @@ class ModelAdmin(BaseModelAdminMixin, ActionModelAdminMixin, BaseModelAdmin):
|
|
152
207
|
+ urls
|
153
208
|
)
|
154
209
|
|
155
|
-
def _path_from_custom_url(self, custom_url) -> URLPattern:
|
210
|
+
def _path_from_custom_url(self, custom_url: tuple[str, str, View]) -> URLPattern:
|
156
211
|
return path(
|
157
212
|
custom_url[0],
|
158
213
|
self.admin_site.admin_view(custom_url[2]),
|
@@ -161,13 +216,15 @@ class ModelAdmin(BaseModelAdminMixin, ActionModelAdminMixin, BaseModelAdmin):
|
|
161
216
|
)
|
162
217
|
|
163
218
|
def get_action_choices(
|
164
|
-
self,
|
165
|
-
|
219
|
+
self,
|
220
|
+
request: HttpRequest,
|
221
|
+
default_choices: list[tuple[str, str]] = BLANK_CHOICE_DASH,
|
222
|
+
) -> list[tuple[str, str]]:
|
166
223
|
default_choices = [("", _("Select action"))]
|
167
224
|
return super().get_action_choices(request, default_choices)
|
168
225
|
|
169
226
|
@display(description=mark_safe(checkbox.render("action_toggle_all", 1)))
|
170
|
-
def action_checkbox(self, obj: Model):
|
227
|
+
def action_checkbox(self, obj: Model) -> str:
|
171
228
|
return checkbox.render(helpers.ACTION_CHECKBOX_NAME, str(obj.pk))
|
172
229
|
|
173
230
|
def response_change(self, request: HttpRequest, obj: Model) -> HttpResponse:
|
@@ -177,14 +234,14 @@ class ModelAdmin(BaseModelAdminMixin, ActionModelAdminMixin, BaseModelAdmin):
|
|
177
234
|
return res
|
178
235
|
|
179
236
|
def response_add(
|
180
|
-
self, request: HttpRequest, obj: Model, post_url_continue:
|
237
|
+
self, request: HttpRequest, obj: Model, post_url_continue: str | None = None
|
181
238
|
) -> HttpResponse:
|
182
239
|
res = super().response_add(request, obj, post_url_continue)
|
183
240
|
if "next" in request.GET:
|
184
241
|
return redirect(request.GET["next"])
|
185
242
|
return res
|
186
243
|
|
187
|
-
def get_changelist(self, request, **kwargs):
|
244
|
+
def get_changelist(self, request: HttpRequest, **kwargs: Any) -> ChangeList:
|
188
245
|
return ChangeList
|
189
246
|
|
190
247
|
def get_formset_kwargs(
|
@@ -198,6 +255,9 @@ class ModelAdmin(BaseModelAdminMixin, ActionModelAdminMixin, BaseModelAdmin):
|
|
198
255
|
|
199
256
|
return formset_kwargs
|
200
257
|
|
258
|
+
def get_changeform_datasets(self, request: HttpRequest) -> list[type[BaseDataset]]:
|
259
|
+
return self.change_form_datasets
|
260
|
+
|
201
261
|
|
202
262
|
class BaseInlineMixin:
|
203
263
|
formfield_overrides = FORMFIELD_OVERRIDES_INLINE
|
unfold/components.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import Any
|
1
|
+
from typing import Any
|
2
2
|
|
3
3
|
from django.http import HttpRequest
|
4
4
|
|
@@ -21,7 +21,7 @@ class ComponentRegistry:
|
|
21
21
|
cls._registry[class_name] = component_cls
|
22
22
|
|
23
23
|
@classmethod
|
24
|
-
def get_class(cls, class_name: str) ->
|
24
|
+
def get_class(cls, class_name: str) -> type | None:
|
25
25
|
return cls._registry.get(class_name)
|
26
26
|
|
27
27
|
@classmethod
|
@@ -4,10 +4,11 @@ from typing import Any
|
|
4
4
|
from django.contrib import admin
|
5
5
|
from django.contrib.admin.views.main import ChangeList
|
6
6
|
from django.core.validators import EMPTY_VALUES
|
7
|
-
from django.db.models import QuerySet
|
7
|
+
from django.db.models import Model, QuerySet
|
8
8
|
from django.http import HttpRequest
|
9
9
|
from django.utils.translation import gettext_lazy as _
|
10
10
|
|
11
|
+
from unfold.admin import ModelAdmin
|
11
12
|
from unfold.contrib.filters.admin.mixins import (
|
12
13
|
ChoicesMixin,
|
13
14
|
MultiValueMixin,
|
@@ -56,6 +57,17 @@ class CheckboxFilter(RadioFilter):
|
|
56
57
|
form_class = CheckboxForm
|
57
58
|
all_option = None
|
58
59
|
|
60
|
+
# TODO: remove once django 4.x is not supported
|
61
|
+
def __init__(
|
62
|
+
self,
|
63
|
+
request: HttpRequest,
|
64
|
+
params: dict[str, Any],
|
65
|
+
model: type[Model],
|
66
|
+
model_admin: ModelAdmin,
|
67
|
+
) -> None:
|
68
|
+
self.request = request
|
69
|
+
super().__init__(request, params, model, model_admin)
|
70
|
+
|
59
71
|
def value(self) -> list[Any]:
|
60
72
|
return self.request.GET.getlist(self.parameter_name)
|
61
73
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
from collections.abc import Generator
|
2
|
-
from typing import Any
|
2
|
+
from typing import Any
|
3
3
|
|
4
4
|
from django.contrib.admin.views.main import ChangeList
|
5
5
|
from django.core.validators import EMPTY_VALUES
|
@@ -18,7 +18,7 @@ from unfold.contrib.filters.forms import (
|
|
18
18
|
|
19
19
|
|
20
20
|
class ValueMixin:
|
21
|
-
def value(self) ->
|
21
|
+
def value(self) -> str | None:
|
22
22
|
return (
|
23
23
|
self.lookup_val[0]
|
24
24
|
if self.lookup_val not in EMPTY_VALUES
|
@@ -29,7 +29,7 @@ class ValueMixin:
|
|
29
29
|
|
30
30
|
|
31
31
|
class MultiValueMixin:
|
32
|
-
def value(self) ->
|
32
|
+
def value(self) -> list[str] | None:
|
33
33
|
return (
|
34
34
|
self.lookup_val
|
35
35
|
if self.lookup_val not in EMPTY_VALUES
|
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import Any
|
1
|
+
from typing import Any
|
2
2
|
|
3
3
|
from django.contrib import admin
|
4
4
|
from django.contrib.admin.options import ModelAdmin
|
@@ -35,7 +35,7 @@ class SingleNumericFilter(admin.FieldListFilter):
|
|
35
35
|
) -> None:
|
36
36
|
super().__init__(field, request, params, model, model_admin, field_path)
|
37
37
|
|
38
|
-
if not isinstance(field,
|
38
|
+
if not isinstance(field, DecimalField | IntegerField | FloatField | AutoField):
|
39
39
|
raise TypeError(
|
40
40
|
f"Class {type(self.field)} is not supported for {self.__class__.__name__}."
|
41
41
|
)
|
@@ -54,7 +54,7 @@ class SingleNumericFilter(admin.FieldListFilter):
|
|
54
54
|
|
55
55
|
def queryset(
|
56
56
|
self, request: HttpRequest, queryset: QuerySet[Any]
|
57
|
-
) ->
|
57
|
+
) -> QuerySet | None:
|
58
58
|
if self.value():
|
59
59
|
try:
|
60
60
|
return queryset.filter(**{self.parameter_name: self.value()})
|
@@ -64,7 +64,7 @@ class SingleNumericFilter(admin.FieldListFilter):
|
|
64
64
|
def value(self) -> Any:
|
65
65
|
return self.used_parameters.get(self.parameter_name, None)
|
66
66
|
|
67
|
-
def expected_parameters(self) -> list[
|
67
|
+
def expected_parameters(self) -> list[str | None]:
|
68
68
|
return [self.parameter_name]
|
69
69
|
|
70
70
|
def choices(self, changelist: ChangeList) -> tuple[dict[str, Any], ...]:
|
@@ -111,7 +111,7 @@ class RangeNumericFilter(RangeNumericMixin, admin.FieldListFilter):
|
|
111
111
|
field_path: str,
|
112
112
|
) -> None:
|
113
113
|
super().__init__(field, request, params, model, model_admin, field_path)
|
114
|
-
if not isinstance(field,
|
114
|
+
if not isinstance(field, DecimalField | IntegerField | FloatField | AutoField):
|
115
115
|
raise TypeError(
|
116
116
|
f"Class {type(self.field)} is not supported for {self.__class__.__name__}."
|
117
117
|
)
|
@@ -156,7 +156,7 @@ class SliderNumericFilter(RangeNumericFilter):
|
|
156
156
|
else:
|
157
157
|
max_value = None
|
158
158
|
|
159
|
-
if isinstance(self.field,
|
159
|
+
if isinstance(self.field, FloatField | DecimalField):
|
160
160
|
decimals = self.MAX_DECIMALS
|
161
161
|
step = self.STEP if self.STEP else self._get_min_step(self.MAX_DECIMALS)
|
162
162
|
else:
|
unfold/contrib/forms/widgets.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import Any
|
1
|
+
from typing import Any
|
2
2
|
|
3
3
|
from django.core.validators import EMPTY_VALUES
|
4
4
|
from django.forms import MultiWidget, Widget
|
@@ -35,7 +35,7 @@ class ArrayWidget(MultiWidget):
|
|
35
35
|
|
36
36
|
def __init__(
|
37
37
|
self,
|
38
|
-
widget_class:
|
38
|
+
widget_class: type[Widget] | None = None,
|
39
39
|
*args: Any,
|
40
40
|
**kwargs: Any,
|
41
41
|
) -> None:
|
@@ -81,7 +81,7 @@ class ArrayWidget(MultiWidget):
|
|
81
81
|
) -> list:
|
82
82
|
return data.getlist(name) not in [[""], *EMPTY_VALUES]
|
83
83
|
|
84
|
-
def decompress(self, value:
|
84
|
+
def decompress(self, value: str | list) -> list:
|
85
85
|
if isinstance(value, list):
|
86
86
|
return value
|
87
87
|
elif isinstance(value, str):
|
@@ -89,7 +89,7 @@ class ArrayWidget(MultiWidget):
|
|
89
89
|
|
90
90
|
return []
|
91
91
|
|
92
|
-
def _resolve_widgets(self, value:
|
92
|
+
def _resolve_widgets(self, value: list | str | None) -> None:
|
93
93
|
if value is None:
|
94
94
|
value = []
|
95
95
|
|
@@ -112,7 +112,7 @@ class WysiwygWidget(Widget):
|
|
112
112
|
"unfold/forms/js/trix.config.js",
|
113
113
|
)
|
114
114
|
|
115
|
-
def __init__(self, attrs:
|
115
|
+
def __init__(self, attrs: dict[str, Any] | None = None) -> None:
|
116
116
|
super().__init__(attrs)
|
117
117
|
|
118
118
|
self.attrs.update(
|
unfold/contrib/inlines/admin.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
from functools import partial
|
2
|
-
from typing import Any
|
2
|
+
from typing import Any
|
3
3
|
|
4
4
|
from django import forms
|
5
5
|
from django.contrib.admin.utils import NestedObjects, flatten_fieldsets
|
@@ -28,7 +28,7 @@ class NonrelatedInlineMixin:
|
|
28
28
|
formset = NonrelatedInlineModelFormSet
|
29
29
|
|
30
30
|
def get_formset(
|
31
|
-
self, request: HttpRequest, obj:
|
31
|
+
self, request: HttpRequest, obj: Model | None = None, **kwargs: Any
|
32
32
|
):
|
33
33
|
defaults = self._get_formset_defaults(request, obj, **kwargs)
|
34
34
|
|
@@ -41,7 +41,7 @@ class NonrelatedInlineMixin:
|
|
41
41
|
)
|
42
42
|
|
43
43
|
def _get_formset_defaults(
|
44
|
-
self, request: HttpRequest, obj:
|
44
|
+
self, request: HttpRequest, obj: Model | None = None, **kwargs: Any
|
45
45
|
):
|
46
46
|
"""Return a BaseInlineFormSet class for use in admin add/change views."""
|
47
47
|
if "fields" in kwargs:
|