django-unfold 0.66.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.66.0.dist-info → django_unfold-0.68.0.dist-info}/METADATA +8 -5
- {django_unfold-0.66.0.dist-info → django_unfold-0.68.0.dist-info}/RECORD +46 -42
- 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 +8 -6
- unfold/contrib/filters/forms.py +25 -4
- unfold/contrib/filters/static/unfold/filters/js/admin-numeric-filter.js +62 -28
- unfold/contrib/filters/templates/unfold/filters/filters_numeric_slider.html +2 -11
- 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 +40 -1
- 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 +65 -5
- unfold/static/unfold/js/select2.init.js +2 -9
- unfold/styles.css +22 -21
- 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/components/card.html +12 -3
- unfold/templates/unfold/components/progress.html +9 -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.html +1 -1
- unfold/templates/unfold/helpers/field_readonly_value_file.html +18 -0
- 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.66.0.dist-info → django_unfold-0.68.0.dist-info}/WHEEL +0 -0
- {django_unfold-0.66.0.dist-info → django_unfold-0.68.0.dist-info}/licenses/LICENSE.md +0 -0
@@ -1,5 +1,5 @@
|
|
1
1
|
import copy
|
2
|
-
from typing import Any
|
2
|
+
from typing import Any
|
3
3
|
|
4
4
|
from django.contrib.admin import helpers
|
5
5
|
from django.contrib.admin.sites import AdminSite
|
@@ -31,9 +31,9 @@ class BaseModelAdminMixin:
|
|
31
31
|
def changeform_view(
|
32
32
|
self,
|
33
33
|
request: HttpRequest,
|
34
|
-
object_id:
|
34
|
+
object_id: str | None = None,
|
35
35
|
form_url: str = "",
|
36
|
-
extra_context:
|
36
|
+
extra_context: dict[str, Any] | None = None,
|
37
37
|
) -> Any:
|
38
38
|
from unfold.forms import AdminForm, Fieldline
|
39
39
|
|
@@ -61,7 +61,7 @@ class BaseModelAdminMixin:
|
|
61
61
|
|
62
62
|
def formfield_for_foreignkey(
|
63
63
|
self, db_field: ForeignKey, request: HttpRequest, **kwargs
|
64
|
-
) ->
|
64
|
+
) -> ModelChoiceField | None:
|
65
65
|
db = kwargs.get("using")
|
66
66
|
|
67
67
|
# Overrides widgets for all related fields
|
@@ -102,7 +102,7 @@ class BaseModelAdminMixin:
|
|
102
102
|
|
103
103
|
def formfield_for_nullboolean_field(
|
104
104
|
self, db_field: Field, request: HttpRequest, **kwargs
|
105
|
-
) ->
|
105
|
+
) -> Field | None:
|
106
106
|
if "widget" not in kwargs:
|
107
107
|
if db_field.choices:
|
108
108
|
kwargs["widget"] = widgets.UnfoldAdminSelectWidget(
|
@@ -115,7 +115,7 @@ class BaseModelAdminMixin:
|
|
115
115
|
|
116
116
|
def formfield_for_dbfield(
|
117
117
|
self, db_field: Field, request: HttpRequest, **kwargs
|
118
|
-
) ->
|
118
|
+
) -> Field | None:
|
119
119
|
if isinstance(db_field, models.BooleanField) and db_field.null is True:
|
120
120
|
return self.formfield_for_nullboolean_field(db_field, request, **kwargs)
|
121
121
|
|
unfold/sites.py
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
import copy
|
2
2
|
import time
|
3
|
+
from collections.abc import Callable
|
3
4
|
from http import HTTPStatus
|
4
|
-
from typing import Any
|
5
|
+
from typing import Any
|
5
6
|
from urllib.parse import parse_qs, urlparse
|
6
7
|
|
7
8
|
from django.contrib.admin import AdminSite
|
@@ -141,7 +142,7 @@ class UnfoldAdminSite(AdminSite):
|
|
141
142
|
return context
|
142
143
|
|
143
144
|
def index(
|
144
|
-
self, request: HttpRequest, extra_context:
|
145
|
+
self, request: HttpRequest, extra_context: dict[str, Any] | None = None
|
145
146
|
) -> TemplateResponse:
|
146
147
|
app_list = self.get_app_list(request)
|
147
148
|
|
@@ -166,7 +167,7 @@ class UnfoldAdminSite(AdminSite):
|
|
166
167
|
)
|
167
168
|
|
168
169
|
def toggle_sidebar(
|
169
|
-
self, request: HttpRequest, extra_context:
|
170
|
+
self, request: HttpRequest, extra_context: dict[str, Any] | None = None
|
170
171
|
) -> HttpResponse:
|
171
172
|
if "toggle_sidebar" not in request.session:
|
172
173
|
request.session["toggle_sidebar"] = True
|
@@ -214,14 +215,14 @@ class UnfoldAdminSite(AdminSite):
|
|
214
215
|
request: HttpRequest,
|
215
216
|
app_list: list[dict[str, Any]],
|
216
217
|
search_term: str,
|
217
|
-
allowed_models:
|
218
|
+
allowed_models: list[str] | None = None,
|
218
219
|
) -> list[SearchResult]:
|
219
220
|
results = []
|
220
221
|
|
221
222
|
for app in app_list:
|
222
223
|
for model in app["models"]:
|
223
224
|
# Skip models which are not allowed
|
224
|
-
if isinstance(allowed_models,
|
225
|
+
if isinstance(allowed_models, list | tuple):
|
225
226
|
if model["model"]._meta.label.lower() not in [
|
226
227
|
m.lower() for m in allowed_models
|
227
228
|
]:
|
@@ -263,7 +264,7 @@ class UnfoldAdminSite(AdminSite):
|
|
263
264
|
return results
|
264
265
|
|
265
266
|
def search(
|
266
|
-
self, request: HttpRequest, extra_context:
|
267
|
+
self, request: HttpRequest, extra_context: dict[str, Any] | None = None
|
267
268
|
) -> TemplateResponse:
|
268
269
|
start_time = time.time()
|
269
270
|
|
@@ -302,10 +303,10 @@ class UnfoldAdminSite(AdminSite):
|
|
302
303
|
self._get_config("COMMAND", request).get("search_models"), request
|
303
304
|
)
|
304
305
|
|
305
|
-
if search_models is True or isinstance(search_models,
|
306
|
+
if search_models is True or isinstance(search_models, list | tuple):
|
306
307
|
allowed_models = (
|
307
308
|
search_models
|
308
|
-
if isinstance(search_models,
|
309
|
+
if isinstance(search_models, list | tuple)
|
309
310
|
else None
|
310
311
|
)
|
311
312
|
|
@@ -340,7 +341,7 @@ class UnfoldAdminSite(AdminSite):
|
|
340
341
|
)
|
341
342
|
|
342
343
|
def password_change(
|
343
|
-
self, request: HttpRequest, extra_context:
|
344
|
+
self, request: HttpRequest, extra_context: dict[str, Any] | None = None
|
344
345
|
) -> HttpResponse:
|
345
346
|
from django.contrib.auth.views import PasswordChangeView
|
346
347
|
|
@@ -462,7 +463,7 @@ class UnfoldAdminSite(AdminSite):
|
|
462
463
|
return tabs
|
463
464
|
|
464
465
|
def _call_permission_callback(
|
465
|
-
self, callback:
|
466
|
+
self, callback: str | Callable | None, request: HttpRequest
|
466
467
|
) -> bool:
|
467
468
|
if callback is None:
|
468
469
|
return True
|
@@ -490,7 +491,7 @@ class UnfoldAdminSite(AdminSite):
|
|
490
491
|
return target
|
491
492
|
|
492
493
|
def _get_is_active(
|
493
|
-
self, request: HttpRequest, link:
|
494
|
+
self, request: HttpRequest, link: str | Callable, is_tab: bool = False
|
494
495
|
) -> bool:
|
495
496
|
if not isinstance(link, str):
|
496
497
|
link = str(link)
|
@@ -545,9 +546,7 @@ class UnfoldAdminSite(AdminSite):
|
|
545
546
|
if key in config and config[key]:
|
546
547
|
return self._get_value(config[key], *args)
|
547
548
|
|
548
|
-
def _get_theme_images(
|
549
|
-
self, key: str, *args: Any
|
550
|
-
) -> Union[dict[str, str], str, None]:
|
549
|
+
def _get_theme_images(self, key: str, *args: Any) -> dict[str, str] | str | None:
|
551
550
|
images = self._get_config(key, *args)
|
552
551
|
|
553
552
|
if isinstance(images, dict):
|
@@ -613,9 +612,7 @@ class UnfoldAdminSite(AdminSite):
|
|
613
612
|
for item in items
|
614
613
|
]
|
615
614
|
|
616
|
-
def _get_value(
|
617
|
-
self, value: Union[str, Callable, lazy, None], *args: Any
|
618
|
-
) -> Optional[str]:
|
615
|
+
def _get_value(self, value: str | Callable | None, *args: Any) -> str | None:
|
619
616
|
if value is None:
|
620
617
|
return None
|
621
618
|
|