django-unfold 0.55.1__py3-none-any.whl → 0.55.3__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: django-unfold
3
- Version: 0.55.1
3
+ Version: 0.55.3
4
4
  Summary: Modern Django admin theme for seamless interface development
5
5
  License: MIT
6
6
  Keywords: django,admin,tailwind,theme
@@ -1,5 +1,5 @@
1
1
  unfold/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- unfold/admin.py,sha256=_dshyJ1LhGZhcx-eRdny9l1OEcIrqxmKzQzpfZcQAY4,6205
2
+ unfold/admin.py,sha256=2YwKqP5slOtqpEInq_u-0-XlddY7Qnj21VeH-lsLkxg,6552
3
3
  unfold/apps.py,sha256=SlBXPYrUd2uXn67qFbRvbXSUk3XFWrF4-5WELgDCvho,381
4
4
  unfold/checks.py,sha256=8I3i4xR_KgyJdpQyZUZzKNeyYf-sNzg6PAlsREuMfgI,1664
5
5
  unfold/components.py,sha256=vqkQzseYUvLXDohmTVAlbKopALjyX4WA9yglvdfhqu4,1283
@@ -7,10 +7,10 @@ unfold/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  unfold/contrib/filters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
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=xptxmUM9FL4xZklBOBnFR0yNlzNAZgEt3xLBtMBgQko,5575
10
+ unfold/contrib/filters/admin/choice_filters.py,sha256=wI_m5k8SLwHkWoFeCPvI0bN_RuF0RNyzRP3z8jor684,5651
11
11
  unfold/contrib/filters/admin/datetime_filters.py,sha256=cVari_7jsfeYxJoRBhcAUOr6v9XdtDtMuMs-S1Irafo,7757
12
- unfold/contrib/filters/admin/dropdown_filters.py,sha256=aBJeutavLRocbrverAUM6mx4_kCyDWKnjcx3JRVqXuc,3837
13
- unfold/contrib/filters/admin/mixins.py,sha256=4SiJ1Qnp-REUXOhk80zq8uW0nc2i-r8aftvSaFrpPXw,5820
12
+ unfold/contrib/filters/admin/dropdown_filters.py,sha256=exiIyU6c_as7XBJsaAPPx5b8eY3IDbuCFGPJu1b0ux4,3856
13
+ unfold/contrib/filters/admin/mixins.py,sha256=Z8BrdqbnjM1Ldr7qfhb6aWeOXKc5NqUgp-1NDU7SqS4,5839
14
14
  unfold/contrib/filters/admin/numeric_filters.py,sha256=8GNmesgMmMIfEZb2IrGbaBoJuvB2FpIc7wPIPBpHat4,6420
15
15
  unfold/contrib/filters/admin/text_filters.py,sha256=19cOEGpSaXafcM8QuGiYaWmNi5UIQnCXEhKG-vCTfe8,2088
16
16
  unfold/contrib/filters/apps.py,sha256=wEySJy0gMLzFLb9XNKE-RexiO05X7NaQ5QmxZyziJ_k,136
@@ -91,7 +91,7 @@ unfold/overrides.py,sha256=ERVY9boZiXgjDYcTEZcIp7KWoeBZ45VM_zN31yAOjyQ,2922
91
91
  unfold/paginator.py,sha256=vWCIfpuWbV3nvIkQOPyD7MLTg2hZplHz3rze42d-qiA,268
92
92
  unfold/sections.py,sha256=Lcg3xCZ76fqjm4vD4x7YdE5VsbTKluL-sX5QTEBlHxA,2379
93
93
  unfold/settings.py,sha256=3ICha2I0oSaHhajG8159nHdNTYJInBtRQq9VziWKYKs,2709
94
- unfold/sites.py,sha256=n1IY7xS4316ZfjcwKWQlnkPtzdVCifbltBT-yZoUu3k,16657
94
+ unfold/sites.py,sha256=fCJItNXLua39Jl66aCfeP88TtQV4MxahjuaQg-luD7Y,16601
95
95
  unfold/static/admin/js/admin/RelatedObjectLookups.js,sha256=alI0-yq7YPDJJJn-yg1ce79-Cv88yQDUrfaGqFZnsaY,9048
96
96
  unfold/static/admin/js/inlines.js,sha256=zcYwLGI_6RHg-gucDbbhp43RRoZd3so8bPk841KFaIE,15573
97
97
  unfold/static/unfold/css/simplebar/LICENSE,sha256=okNJf6UFl2NrEiC4iqORNBa16IKgUgV88acdcl9FbtY,1081
@@ -136,13 +136,13 @@ unfold/templates/admin/change_list_results.html,sha256=H7JtxfZSRIwYQTYdBAumFpkAT
136
136
  unfold/templates/admin/date_hierarchy.html,sha256=Jl_Vk05fXvsSvod5Dw2p3KhpCQGjtSX1zqlNjjkBFR4,1411
137
137
  unfold/templates/admin/delete_confirmation.html,sha256=yT_NHbFHZEjkSCaGVcM52GCG-FDmWiJdTFLbq9CBCx4,4619
138
138
  unfold/templates/admin/delete_selected_confirmation.html,sha256=QR0JhrPR8YI8KpQnB3xyrKxaui-_pEQmfaMDbcXjjZ0,4391
139
- unfold/templates/admin/edit_inline/stacked.html,sha256=-ASy7Jd0SwWBDxurucbus86YT2AokJEcCUrqPlHVDQA,7644
140
- unfold/templates/admin/edit_inline/tabular.html,sha256=GFXgOwMK0WZfFtMdfw7JMAXTUmW7cavEh9FYQ2dTgh4,2893
139
+ unfold/templates/admin/edit_inline/stacked.html,sha256=AKxHohBigWejvUkuxiutmPGiXTgX5puYLEh2ilb1oKw,7641
140
+ unfold/templates/admin/edit_inline/tabular.html,sha256=T78t2UBOd11e4ZQu1Bk46FTMrxw7vHdcOCyS12Vl_kE,2890
141
141
  unfold/templates/admin/filter.html,sha256=0B_hpLybHw1wUPPCN3KJvoWrx03iFeqP8m1LRCjnLlQ,2012
142
142
  unfold/templates/admin/includes/fieldset.html,sha256=gX-dc-jPLswk21XSKUXzAU8WFl3CFfeVrIAU2bviPyg,812
143
143
  unfold/templates/admin/includes/object_delete_summary.html,sha256=FgwfapZCKWtnFtTHqh1MRuxxLot4bAw92WCcR_V8ImI,444
144
144
  unfold/templates/admin/index.html,sha256=JnNDpNKqFKVKMQvpUQo6ddcFqGadK5g78pxpKAHLuMU,583
145
- unfold/templates/admin/login.html,sha256=5khGm_cafDVQaDRwaTtix4g2DH4R4LrwgqO0S4aumaE,4476
145
+ unfold/templates/admin/login.html,sha256=p99KEDfFdNeJLapiOdWdRyAsQjcpYT27v2aoC51u3RM,4549
146
146
  unfold/templates/admin/nav_sidebar.html,sha256=cadJwXcReRHwVTpXGycF3uv5VZ5JDcIbY1pCabeQlCo,250
147
147
  unfold/templates/admin/object_history.html,sha256=bfad4_lfLQFcoMV67yW7BnAi1Hwrptmgxj2tgPYQjtI,4816
148
148
  unfold/templates/admin/pagination.html,sha256=k0OfgbKSu6HzP0zfAOHC4hswFk1Xc8XEQYfuqJxQQT4,1734
@@ -226,7 +226,7 @@ unfold/templates/unfold/helpers/site_logo.html,sha256=S_QJoT2qh0xw0ciaKxoT4GJ6QI
226
226
  unfold/templates/unfold/helpers/submit.html,sha256=4Mgf4lx7Atm8GPqD6LTJK3NA9zoSJjs9VPig7sDp8Ao,203
227
227
  unfold/templates/unfold/helpers/tab_action.html,sha256=ODm7ws5sbhpE4OvGuQbzynlVwk6AJRreMUra6hh1lxM,3306
228
228
  unfold/templates/unfold/helpers/tab_actions.html,sha256=DMNqY1YyrNrcutOMC3J1neZZjIkPeYShp1i5xZ10nrc,695
229
- unfold/templates/unfold/helpers/tab_items.html,sha256=Gi6cjYJ7tJWO6zSXjg8xNHY9ALpYzjQOEORusf_AZfg,3325
229
+ unfold/templates/unfold/helpers/tab_items.html,sha256=aVArF14KbzY-HhhsRww2rkM77StbBSpEIyAltmNwH2M,3337
230
230
  unfold/templates/unfold/helpers/tab_list.html,sha256=Tqkug9GyoIQ2geVKWrnnuE0bxeTRXj0MSEwwixoOGz4,436
231
231
  unfold/templates/unfold/helpers/theme_switch.html,sha256=Kh3Q8RuBWCUuY8YJLwBwd5yKzDhK6y0Ggx_ERoGEGv8,2218
232
232
  unfold/templates/unfold/helpers/userlinks.html,sha256=oZqiwCxG_zRecAbzYrr8_hQvkndVB6-liP6LEZM1UZc,863
@@ -276,7 +276,7 @@ unfold/typing.py,sha256=i7LM2LiwYTAjT5-OLDUPVn5b9X-DMmHnjlZG2toWwSE,692
276
276
  unfold/utils.py,sha256=SJikRuAuJN0bE9rfzUujZwycTRrzQm14Hk0zB0EwivU,6164
277
277
  unfold/views.py,sha256=FuYnMrlg6SegLUDDN6An__yZj8rchD_iBK8myieYhkA,1492
278
278
  unfold/widgets.py,sha256=-l0eRljJheVWhTtD0nTvNuY1dvNmwtfd-aqXdSVr-q0,22344
279
- django_unfold-0.55.1.dist-info/LICENSE.md,sha256=Ltk_quRyyvV3J5v3brtOqmibeZSw2Hrb8bY1W3ya0Ik,1077
280
- django_unfold-0.55.1.dist-info/METADATA,sha256=t0DhmEvjtNDYPVLS_fO_1pGZSp-9BWhGe1rrL4_zmPI,7951
281
- django_unfold-0.55.1.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
282
- django_unfold-0.55.1.dist-info/RECORD,,
279
+ django_unfold-0.55.3.dist-info/LICENSE.md,sha256=Ltk_quRyyvV3J5v3brtOqmibeZSw2Hrb8bY1W3ya0Ik,1077
280
+ django_unfold-0.55.3.dist-info/METADATA,sha256=2E2tIOsUqXkPmzHxRa-46qXPkPeA28NSY0M389Hrzs0,7951
281
+ django_unfold-0.55.3.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
282
+ django_unfold-0.55.3.dist-info/RECORD,,
unfold/admin.py CHANGED
@@ -9,6 +9,7 @@ from django.contrib.admin import display, helpers
9
9
  from django.db.models import BLANK_CHOICE_DASH, Model
10
10
  from django.http import HttpRequest, HttpResponse
11
11
  from django.shortcuts import redirect
12
+ from django.template.response import TemplateResponse
12
13
  from django.urls import URLPattern, path
13
14
  from django.utils.safestring import mark_safe
14
15
  from django.utils.translation import gettext_lazy as _
@@ -56,12 +57,12 @@ class ModelAdmin(BaseModelAdminMixin, ActionModelAdminMixin, BaseModelAdmin):
56
57
  warn_unsaved_form = False
57
58
  checks_class = UnfoldModelAdminChecks
58
59
 
59
- @property
60
- def media(self):
61
- media = super().media
60
+ def changelist_view(
61
+ self, request: HttpRequest, extra_context: Optional[dict[str, str]] = None
62
+ ) -> TemplateResponse:
62
63
  additional_media = forms.Media()
63
64
 
64
- for filter in self.list_filter:
65
+ for filter in self.get_list_filter(request):
65
66
  if (
66
67
  isinstance(filter, (tuple, list))
67
68
  and hasattr(filter[1], "form_class")
@@ -71,7 +72,16 @@ class ModelAdmin(BaseModelAdminMixin, ActionModelAdminMixin, BaseModelAdmin):
71
72
  elif hasattr(filter, "form_class") and hasattr(filter.form_class, "Media"):
72
73
  additional_media += forms.Media(filter.form_class.Media)
73
74
 
74
- return media + additional_media
75
+ if not extra_context:
76
+ extra_context = {}
77
+
78
+ extra_context.update(
79
+ {
80
+ "media": self.media + additional_media,
81
+ }
82
+ )
83
+
84
+ return super().changelist_view(request, extra_context)
75
85
 
76
86
  def get_fieldsets(self, request: HttpRequest, obj=None) -> FieldsetsType:
77
87
  if not obj and self.add_fieldsets:
@@ -22,7 +22,7 @@ class RadioFilter(admin.SimpleListFilter):
22
22
  all_option = ["", _("All")]
23
23
 
24
24
  def choices(self, changelist: ChangeList) -> tuple[dict[str, Any], ...]:
25
- add_facets = changelist.add_facets
25
+ add_facets = getattr(changelist, "add_facets", False)
26
26
  facet_counts = self.get_facet_queryset(changelist) if add_facets else None
27
27
  choices = []
28
28
 
@@ -78,7 +78,7 @@ class BooleanRadioFilter(ValueMixin, admin.BooleanFieldListFilter):
78
78
  all_option = ["", _("All")]
79
79
 
80
80
  def choices(self, changelist: ChangeList) -> Generator[dict[str, Any], None, None]:
81
- add_facets = changelist.add_facets
81
+ add_facets = getattr(changelist, "add_facets", False)
82
82
  facet_counts = self.get_facet_queryset(changelist) if add_facets else None
83
83
 
84
84
  if add_facets:
@@ -119,7 +119,7 @@ class RelatedCheckboxFilter(MultiValueMixin, admin.RelatedFieldListFilter):
119
119
  return queryset
120
120
 
121
121
  def choices(self, changelist: ChangeList) -> Generator[dict[str, Any], None, None]:
122
- add_facets = changelist.add_facets
122
+ add_facets = getattr(changelist, "add_facets", False)
123
123
  facet_counts = self.get_facet_queryset(changelist) if add_facets else None
124
124
 
125
125
  if add_facets:
@@ -147,7 +147,7 @@ class AllValuesCheckboxFilter(MultiValueMixin, admin.AllValuesFieldListFilter):
147
147
  form_class = CheckboxForm
148
148
 
149
149
  def choices(self, changelist: ChangeList) -> Generator[dict[str, Any], None, None]:
150
- add_facets = changelist.add_facets
150
+ add_facets = getattr(changelist, "add_facets", False)
151
151
  facet_counts = self.get_facet_queryset(changelist) if add_facets else None
152
152
 
153
153
  if add_facets:
@@ -86,7 +86,7 @@ class RelatedDropdownFilter(ValueMixin, DropdownMixin, admin.RelatedFieldListFil
86
86
  self.request = request
87
87
 
88
88
  def choices(self, changelist: ChangeList) -> Generator[dict[str, Any], None, None]:
89
- add_facets = changelist.add_facets
89
+ add_facets = getattr(changelist, "add_facets", False)
90
90
  facet_counts = self.get_facet_queryset(changelist) if add_facets else None
91
91
 
92
92
  if add_facets:
@@ -55,7 +55,7 @@ class ChoicesMixin:
55
55
  template = "unfold/filters/filters_field.html"
56
56
 
57
57
  def choices(self, changelist: ChangeList) -> Generator[dict[str, Any], None, None]:
58
- add_facets = changelist.add_facets
58
+ add_facets = getattr(changelist, "add_facets", False)
59
59
  facet_counts = self.get_facet_queryset(changelist) if add_facets else None
60
60
  choices = [self.all_option] if self.all_option else []
61
61
 
unfold/sites.py CHANGED
@@ -82,9 +82,9 @@ class UnfoldAdminSite(AdminSite):
82
82
  "switch": " ".join(SWITCH_CLASSES),
83
83
  "file": " ".join(FILE_CLASSES),
84
84
  },
85
- "site_title": self._get_config("SITE_TITLE", request) or self.site_title,
86
- "site_header": self._get_config("SITE_HEADER", request) or self.site_header,
87
- "site_url": self._get_config("SITE_URL", request) or self.site_url,
85
+ "site_title": self._get_config("SITE_TITLE", request),
86
+ "site_header": self._get_config("SITE_HEADER", request),
87
+ "site_url": self._get_config("SITE_URL", request),
88
88
  "site_subheader": self._get_config("SITE_SUBHEADER", request),
89
89
  "site_dropdown": self._get_site_dropdown_items("SITE_DROPDOWN", request),
90
90
  "site_logo": self._get_theme_images("SITE_LOGO", request),
@@ -1,6 +1,6 @@
1
1
  {% load admin_urls i18n unfold %}
2
2
 
3
- <div class="js-inline-admin-formset inline-group" id="{{ inline_admin_formset.formset.prefix }}-group" data-inline-type="stacked" data-inline-formset="{{ inline_admin_formset.inline_formset_data }}" {% if inline_admin_formset.opts.tab %}x-show="activeTab == '{{ inline_admin_formset.opts.verbose_name|slugify }}'"{% else %}x-show="activeTab == 'general'"{% endif %}>
3
+ <div class="js-inline-admin-formset inline-group" id="{{ inline_admin_formset.formset.prefix }}-group" data-inline-type="stacked" data-inline-formset="{{ inline_admin_formset.inline_formset_data }}" {% if inline_admin_formset.opts.tab %}x-show="activeTab == '{{ inline_admin_formset.formset.prefix|slugify }}'"{% else %}x-show="activeTab == 'general'"{% endif %}>
4
4
  <fieldset class="module relative {{ inline_admin_formset.classes }}" aria-labelledby="{{ inline_admin_formset.formset.prefix }}-heading">
5
5
  {% if inline_admin_formset.is_collapsible %}<details><summary>{% endif %}
6
6
 
@@ -1,6 +1,6 @@
1
1
  {% load admin_modify admin_urls i18n static unfold %}
2
2
 
3
- <div class="js-inline-admin-formset inline-group" id="{{ inline_admin_formset.formset.prefix }}-group" data-inline-type="tabular" data-inline-formset="{{ inline_admin_formset.inline_formset_data }}" {% if inline_admin_formset.opts.tab %}x-show="activeTab == '{{ inline_admin_formset.opts.verbose_name|slugify }}'"{% else %}x-show="activeTab == 'general'"{% endif %}>
3
+ <div class="js-inline-admin-formset inline-group" id="{{ inline_admin_formset.formset.prefix }}-group" data-inline-type="tabular" data-inline-formset="{{ inline_admin_formset.inline_formset_data }}" {% if inline_admin_formset.opts.tab %}x-show="activeTab == '{{ inline_admin_formset.formset.prefix|slugify }}'"{% else %}x-show="activeTab == 'general'"{% endif %}>
4
4
  <div class="tabular inline-related {% if forloop.last %}last-related{% endif %}">
5
5
  {{ inline_admin_formset.formset.management_form }}
6
6
 
@@ -90,7 +90,9 @@
90
90
  {% endif %}
91
91
 
92
92
  {% if not theme %}
93
- {% include "unfold/helpers/theme_switch.html" %}
93
+ <div class="ml-auto">
94
+ {% include "unfold/helpers/theme_switch.html" %}
95
+ </div>
94
96
  {% endif %}
95
97
  </div>
96
98
  </div>
@@ -5,11 +5,11 @@
5
5
  {% for item in tabs_list %}
6
6
  {% if item.has_permission %}
7
7
  <li class="border-b last:border-b-0 md:border-b-0 md:mr-8 dark:border-base-800">
8
- <a href="{% if item.link_callback %}{{ item.link_callback }}{% else %}{{ item.link }}{% endif %}{% if item.inline %}#{{ item.inline }}{% endif %}"
8
+ <a href="{% if item.link_callback %}{{ item.link_callback }}{% else %}{{ item.link }}{% endif %}{% if item.inline %}#{{ item.inline|slugify }}{% endif %}"
9
9
  class="block px-3 py-2 md:py-4 md:px-0 dark:border-base-800 {% if item.active and not item.inline %} border-b font-semibold -mb-px text-primary-600 hover:text-primary-600 dark:text-primary-500 dark:hover:text-primary-500 md:border-primary-500 dark:md:!border-primary-600{% else %}font-medium hover:text-primary-600 dark:hover:text-primary-500{% endif %}"
10
10
  {% if item.inline %}
11
- x-on:click="activeTab = '{{ item.inline }}'"
12
- x-bind:class="{'border-b border-base-200 dark:border-base-800 md:border-primary-500 dark:md:!border-primary-600 font-semibold -mb-px text-primary-600 dark:text-primary-500': activeTab == '{{ item.inline }}'}"
11
+ x-on:click="activeTab = '{{ item.inline|slugify }}'"
12
+ x-bind:class="{'border-b border-base-200 dark:border-base-800 md:border-primary-500 dark:md:!border-primary-600 font-semibold -mb-px text-primary-600 dark:text-primary-500': activeTab == '{{ item.inline|slugify }}'}"
13
13
  {% endif %}
14
14
  >
15
15
  {{ item.title }}
@@ -31,9 +31,9 @@
31
31
  {% for inline in inlines_list %}
32
32
  <li class="border-b last:border-b-0 md:border-b-0 md:mr-8 dark:border-base-800">
33
33
  <a class="block cursor-pointer font-medium px-3 py-2 md:py-4 md:px-0"
34
- href="#{{ inline.opts.verbose_name|slugify }}"
35
- x-on:click="activeTab = '{{ inline.opts.verbose_name|slugify }}'"
36
- x-bind:class="{'border-b border-base-200 dark:border-base-800 md:border-primary-500 dark:md:!border-primary-600 font-semibold -mb-px text-primary-600 dark:text-primary-500': activeTab == '{{ inline.opts.verbose_name|slugify }}', 'hover:text-primary-600 dark:hover:text-primary-500 dark:border-base-800': activeTab != '{{ inline.opts.verbose_name|slugify }}'}">
34
+ href="#{{ inline.formset.prefix|slugify }}"
35
+ x-on:click="activeTab = '{{ inline.formset.prefix|slugify }}'"
36
+ x-bind:class="{'border-b border-base-200 dark:border-base-800 md:border-primary-500 dark:md:!border-primary-600 font-semibold -mb-px text-primary-600 dark:text-primary-500': activeTab == '{{ inline.formset.prefix|slugify }}', 'hover:text-primary-600 dark:hover:text-primary-500 dark:border-base-800': activeTab != '{{ inline.formset.prefix|slugify }}'}">
37
37
  {% if inline.formset.max_num == 1 %}
38
38
  {{ inline.opts.verbose_name|capfirst }}
39
39
  {% else %}