django-unfold 0.64.2__py3-none-any.whl → 0.66.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.64.2.dist-info → django_unfold-0.66.0.dist-info}/METADATA +4 -2
- {django_unfold-0.64.2.dist-info → django_unfold-0.66.0.dist-info}/RECORD +34 -33
- {django_unfold-0.64.2.dist-info → django_unfold-0.66.0.dist-info}/WHEEL +1 -1
- unfold/admin.py +15 -16
- unfold/contrib/constance/settings.py +1 -0
- unfold/contrib/constance/templates/admin/constance/change_list.html +18 -18
- unfold/contrib/constance/templates/admin/constance/includes/results_list.html +13 -11
- unfold/contrib/location_field/templates/location_field/map_widget.html +1 -1
- unfold/dataclasses.py +1 -0
- unfold/mixins/base_model_admin.py +1 -1
- unfold/sites.py +45 -18
- unfold/static/unfold/css/styles.css +1 -1
- unfold/static/unfold/js/app.js +56 -11
- unfold/styles.css +24 -10
- unfold/templates/admin/change_form.html +6 -2
- unfold/templates/admin/nav_sidebar.html +1 -1
- unfold/templates/unfold/components/button.html +1 -1
- unfold/templates/unfold/components/card.html +3 -3
- unfold/templates/unfold/components/layer.html +1 -0
- unfold/templates/unfold/components/progress.html +8 -8
- unfold/templates/unfold/components/tracker.html +1 -1
- unfold/templates/unfold/helpers/app_list.html +1 -1
- unfold/templates/unfold/helpers/boolean.html +1 -1
- unfold/templates/unfold/helpers/command.html +1 -1
- unfold/templates/unfold/helpers/command_results.html +31 -12
- unfold/templates/unfold/helpers/header_back_button.html +1 -1
- unfold/templates/unfold/helpers/pagination_infinite.html +1 -1
- unfold/templates/unfold/helpers/search.html +1 -0
- unfold/templates/unfold/helpers/site_dropdown.html +1 -1
- unfold/templates/unfold/widgets/clearable_file_input_small.html +1 -1
- unfold/templatetags/unfold.py +72 -22
- unfold/views.py +2 -0
- unfold/widgets.py +5 -3
- {django_unfold-0.64.2.dist-info → django_unfold-0.66.0.dist-info/licenses}/LICENSE.md +0 -0
unfold/templatetags/unfold.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import json
|
2
|
-
from collections.abc import Mapping
|
2
|
+
from collections.abc import Iterable, Mapping
|
3
3
|
from typing import Any, Optional, Union
|
4
4
|
|
5
5
|
from django import template
|
@@ -235,18 +235,24 @@ class RenderComponentNode(template.Node):
|
|
235
235
|
name: var.resolve(context) for name, var in self.extra_context.items()
|
236
236
|
}
|
237
237
|
|
238
|
-
values.update(
|
239
|
-
{
|
240
|
-
"children": self.nodelist.render(context),
|
241
|
-
}
|
242
|
-
)
|
243
|
-
|
244
238
|
if "component_class" in values:
|
245
239
|
values = ComponentRegistry.create_instance(
|
246
240
|
values["component_class"],
|
247
241
|
request=context.request if hasattr(context, "request") else None,
|
248
242
|
).get_context_data(**values)
|
249
243
|
|
244
|
+
context_copy = context.new()
|
245
|
+
context_copy.update(context.flatten())
|
246
|
+
context_copy.update(values)
|
247
|
+
children = self.nodelist.render(context_copy)
|
248
|
+
|
249
|
+
if len(children) > 0:
|
250
|
+
values.update(
|
251
|
+
{
|
252
|
+
"children": children,
|
253
|
+
}
|
254
|
+
)
|
255
|
+
|
250
256
|
if self.include_context:
|
251
257
|
values.update(context.flatten())
|
252
258
|
|
@@ -548,7 +554,7 @@ def changeform_data(adminform: AdminForm) -> str:
|
|
548
554
|
return mark_safe(json.dumps(fields))
|
549
555
|
|
550
556
|
|
551
|
-
@register.filter
|
557
|
+
@register.filter
|
552
558
|
def changeform_condition(field: BoundField) -> BoundField:
|
553
559
|
if isinstance(field.field, dict):
|
554
560
|
return field
|
@@ -607,15 +613,51 @@ def querystring_params(
|
|
607
613
|
return result.urlencode()
|
608
614
|
|
609
615
|
|
616
|
+
@register.simple_tag(name="unfold_querystring", takes_context=True)
|
617
|
+
def unfold_querystring(context, *args, **kwargs):
|
618
|
+
"""
|
619
|
+
Duplicated querystring template tag from Django core to allow
|
620
|
+
it using in Django 4.x. Once 4.x is not supported, remove it.
|
621
|
+
"""
|
622
|
+
if not args:
|
623
|
+
args = [context.request.GET]
|
624
|
+
params = QueryDict(mutable=True)
|
625
|
+
for d in [*args, kwargs]:
|
626
|
+
if not isinstance(d, Mapping):
|
627
|
+
raise TemplateSyntaxError(
|
628
|
+
"querystring requires mappings for positional arguments (got "
|
629
|
+
f"{d!r} instead)."
|
630
|
+
)
|
631
|
+
for key, value in d.items():
|
632
|
+
if not isinstance(key, str):
|
633
|
+
raise TemplateSyntaxError(
|
634
|
+
f"querystring requires strings for mapping keys (got {key!r} "
|
635
|
+
"instead)."
|
636
|
+
)
|
637
|
+
if value is None:
|
638
|
+
params.pop(key, None)
|
639
|
+
elif isinstance(value, Iterable) and not isinstance(value, str):
|
640
|
+
params.setlist(key, value)
|
641
|
+
else:
|
642
|
+
params[key] = value
|
643
|
+
query_string = params.urlencode() if params else ""
|
644
|
+
return f"?{query_string}"
|
645
|
+
|
646
|
+
|
610
647
|
@register.simple_tag(takes_context=True)
|
611
648
|
def header_title(context: RequestContext) -> str:
|
612
649
|
parts = []
|
613
650
|
opts = context.get("opts")
|
651
|
+
current_app = (
|
652
|
+
context.request.current_app
|
653
|
+
if hasattr(context.request, "current_app")
|
654
|
+
else "admin"
|
655
|
+
)
|
614
656
|
|
615
657
|
if opts:
|
616
658
|
parts.append(
|
617
659
|
{
|
618
|
-
"link": reverse_lazy("
|
660
|
+
"link": reverse_lazy(f"{current_app}:app_list", args=[opts.app_label]),
|
619
661
|
"title": opts.app_config.verbose_name,
|
620
662
|
}
|
621
663
|
)
|
@@ -624,7 +666,7 @@ def header_title(context: RequestContext) -> str:
|
|
624
666
|
parts.append(
|
625
667
|
{
|
626
668
|
"link": reverse_lazy(
|
627
|
-
f"
|
669
|
+
f"{current_app}:{original._meta.app_label}_{original._meta.model_name}_changelist"
|
628
670
|
),
|
629
671
|
"title": original._meta.verbose_name_plural,
|
630
672
|
}
|
@@ -633,7 +675,7 @@ def header_title(context: RequestContext) -> str:
|
|
633
675
|
parts.append(
|
634
676
|
{
|
635
677
|
"link": reverse_lazy(
|
636
|
-
f"
|
678
|
+
f"{current_app}:{original._meta.app_label}_{original._meta.model_name}_change",
|
637
679
|
args=[original.pk],
|
638
680
|
),
|
639
681
|
"title": original,
|
@@ -643,7 +685,7 @@ def header_title(context: RequestContext) -> str:
|
|
643
685
|
parts.append(
|
644
686
|
{
|
645
687
|
"link": reverse_lazy(
|
646
|
-
f"
|
688
|
+
f"{current_app}:{object._meta.app_label}_{object._meta.model_name}_changelist"
|
647
689
|
),
|
648
690
|
"title": object._meta.verbose_name_plural,
|
649
691
|
}
|
@@ -652,7 +694,7 @@ def header_title(context: RequestContext) -> str:
|
|
652
694
|
parts.append(
|
653
695
|
{
|
654
696
|
"link": reverse_lazy(
|
655
|
-
f"
|
697
|
+
f"{current_app}:{object._meta.app_label}_{object._meta.model_name}_change",
|
656
698
|
args=[object.pk],
|
657
699
|
),
|
658
700
|
"title": object,
|
@@ -662,7 +704,7 @@ def header_title(context: RequestContext) -> str:
|
|
662
704
|
parts.append(
|
663
705
|
{
|
664
706
|
"link": reverse_lazy(
|
665
|
-
f"
|
707
|
+
f"{current_app}:{opts.app_label}_{opts.model_name}_changelist"
|
666
708
|
),
|
667
709
|
"title": opts.verbose_name_plural,
|
668
710
|
}
|
@@ -670,7 +712,9 @@ def header_title(context: RequestContext) -> str:
|
|
670
712
|
elif object := context.get("object"):
|
671
713
|
parts.append(
|
672
714
|
{
|
673
|
-
"link": reverse_lazy(
|
715
|
+
"link": reverse_lazy(
|
716
|
+
f"{current_app}:app_list", args=[object._meta.app_label]
|
717
|
+
),
|
674
718
|
"title": object._meta.app_label,
|
675
719
|
}
|
676
720
|
)
|
@@ -678,7 +722,7 @@ def header_title(context: RequestContext) -> str:
|
|
678
722
|
parts.append(
|
679
723
|
{
|
680
724
|
"link": reverse_lazy(
|
681
|
-
f"
|
725
|
+
f"{current_app}:{object._meta.app_label}_{object._meta.model_name}_changelist",
|
682
726
|
),
|
683
727
|
"title": object._meta.verbose_name_plural,
|
684
728
|
}
|
@@ -687,7 +731,7 @@ def header_title(context: RequestContext) -> str:
|
|
687
731
|
parts.append(
|
688
732
|
{
|
689
733
|
"link": reverse_lazy(
|
690
|
-
f"
|
734
|
+
f"{current_app}:{object._meta.app_label}_{object._meta.model_name}_change",
|
691
735
|
args=[object.pk],
|
692
736
|
),
|
693
737
|
"title": object,
|
@@ -697,7 +741,7 @@ def header_title(context: RequestContext) -> str:
|
|
697
741
|
parts.append(
|
698
742
|
{
|
699
743
|
"link": reverse_lazy(
|
700
|
-
"
|
744
|
+
f"{current_app}:app_list", args=[model_admin.model._meta.app_label]
|
701
745
|
),
|
702
746
|
"title": model_admin.model._meta.app_label,
|
703
747
|
}
|
@@ -706,7 +750,7 @@ def header_title(context: RequestContext) -> str:
|
|
706
750
|
parts.append(
|
707
751
|
{
|
708
752
|
"link": reverse_lazy(
|
709
|
-
f"
|
753
|
+
f"{current_app}:{model_admin.model._meta.app_label}_{model_admin.model._meta.model_name}_changelist",
|
710
754
|
),
|
711
755
|
"title": model_admin.model._meta.verbose_name_plural,
|
712
756
|
}
|
@@ -734,9 +778,15 @@ def header_title(context: RequestContext) -> str:
|
|
734
778
|
)
|
735
779
|
|
736
780
|
|
737
|
-
@register.
|
738
|
-
def admin_object_app_url(object: Model, arg: str) -> str:
|
739
|
-
|
781
|
+
@register.simple_tag(takes_context=True)
|
782
|
+
def admin_object_app_url(context: RequestContext, object: Model, arg: str) -> str:
|
783
|
+
current_app = (
|
784
|
+
context.request.current_app
|
785
|
+
if hasattr(context.request, "current_app")
|
786
|
+
else "admin"
|
787
|
+
)
|
788
|
+
|
789
|
+
return f"{current_app}:{object._meta.app_label}_{object._meta.model_name}_{arg}"
|
740
790
|
|
741
791
|
|
742
792
|
@register.filter
|
unfold/views.py
CHANGED
@@ -30,6 +30,8 @@ class UnfoldModelAdminViewMixin(PermissionRequiredMixin):
|
|
30
30
|
super().__init__(**kwargs)
|
31
31
|
|
32
32
|
def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
|
33
|
+
self.request.current_app = self.model_admin.admin_site.name
|
34
|
+
|
33
35
|
if not hasattr(self, "model_admin"):
|
34
36
|
raise UnfoldException(
|
35
37
|
"UnfoldModelAdminViewMixin was not provided with 'model_admin' argument"
|
unfold/widgets.py
CHANGED
@@ -87,6 +87,8 @@ BASE_CLASSES = [
|
|
87
87
|
"dark:focus:group-[.errors]:outline-red-500",
|
88
88
|
"dark:scheme-dark",
|
89
89
|
"group-[.primary]:border-transparent",
|
90
|
+
"disabled:!bg-base-50",
|
91
|
+
"dark:disabled:!bg-base-800",
|
90
92
|
]
|
91
93
|
|
92
94
|
BASE_INPUT_CLASSES = [
|
@@ -252,9 +254,9 @@ SWITCH_CLASSES = [
|
|
252
254
|
"transition-colors",
|
253
255
|
"w-8",
|
254
256
|
"min-w-8",
|
255
|
-
"
|
256
|
-
"
|
257
|
-
"focus:outline-
|
257
|
+
"disabled:cursor-not-allowed",
|
258
|
+
"disabled:opacity-50",
|
259
|
+
"focus:outline-none",
|
258
260
|
"after:absolute",
|
259
261
|
"after:bg-white",
|
260
262
|
"after:content-['']",
|
File without changes
|