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.
Files changed (34) hide show
  1. {django_unfold-0.64.2.dist-info → django_unfold-0.66.0.dist-info}/METADATA +4 -2
  2. {django_unfold-0.64.2.dist-info → django_unfold-0.66.0.dist-info}/RECORD +34 -33
  3. {django_unfold-0.64.2.dist-info → django_unfold-0.66.0.dist-info}/WHEEL +1 -1
  4. unfold/admin.py +15 -16
  5. unfold/contrib/constance/settings.py +1 -0
  6. unfold/contrib/constance/templates/admin/constance/change_list.html +18 -18
  7. unfold/contrib/constance/templates/admin/constance/includes/results_list.html +13 -11
  8. unfold/contrib/location_field/templates/location_field/map_widget.html +1 -1
  9. unfold/dataclasses.py +1 -0
  10. unfold/mixins/base_model_admin.py +1 -1
  11. unfold/sites.py +45 -18
  12. unfold/static/unfold/css/styles.css +1 -1
  13. unfold/static/unfold/js/app.js +56 -11
  14. unfold/styles.css +24 -10
  15. unfold/templates/admin/change_form.html +6 -2
  16. unfold/templates/admin/nav_sidebar.html +1 -1
  17. unfold/templates/unfold/components/button.html +1 -1
  18. unfold/templates/unfold/components/card.html +3 -3
  19. unfold/templates/unfold/components/layer.html +1 -0
  20. unfold/templates/unfold/components/progress.html +8 -8
  21. unfold/templates/unfold/components/tracker.html +1 -1
  22. unfold/templates/unfold/helpers/app_list.html +1 -1
  23. unfold/templates/unfold/helpers/boolean.html +1 -1
  24. unfold/templates/unfold/helpers/command.html +1 -1
  25. unfold/templates/unfold/helpers/command_results.html +31 -12
  26. unfold/templates/unfold/helpers/header_back_button.html +1 -1
  27. unfold/templates/unfold/helpers/pagination_infinite.html +1 -1
  28. unfold/templates/unfold/helpers/search.html +1 -0
  29. unfold/templates/unfold/helpers/site_dropdown.html +1 -1
  30. unfold/templates/unfold/widgets/clearable_file_input_small.html +1 -1
  31. unfold/templatetags/unfold.py +72 -22
  32. unfold/views.py +2 -0
  33. unfold/widgets.py +5 -3
  34. {django_unfold-0.64.2.dist-info → django_unfold-0.66.0.dist-info/licenses}/LICENSE.md +0 -0
@@ -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(takes_context=True)
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("admin:app_list", args=[opts.app_label]),
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"admin:{original._meta.app_label}_{original._meta.model_name}_changelist"
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"admin:{original._meta.app_label}_{original._meta.model_name}_change",
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"admin:{object._meta.app_label}_{object._meta.model_name}_changelist"
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"admin:{object._meta.app_label}_{object._meta.model_name}_change",
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"admin:{opts.app_label}_{opts.model_name}_changelist"
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("admin:app_list", args=[object._meta.app_label]),
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"admin:{object._meta.app_label}_{object._meta.model_name}_changelist",
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"admin:{object._meta.app_label}_{object._meta.model_name}_change",
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
- "admin:app_list", args=[model_admin.model._meta.app_label]
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"admin:{model_admin.model._meta.app_label}_{model_admin.model._meta.model_name}_changelist",
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.filter
738
- def admin_object_app_url(object: Model, arg: str) -> str:
739
- return f"admin:{object._meta.app_label}_{object._meta.model_name}_{arg}"
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
- "focus:outline-2",
256
- "focus:outline-offset-2",
257
- "focus:outline-primary-600",
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-['']",