django-smartbase-admin 1.0.9__py3-none-any.whl → 1.0.11__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_smartbase_admin/actions/admin_action_list.py +15 -15
- django_smartbase_admin/admin/admin_base.py +29 -4
- django_smartbase_admin/admin/widgets.py +3 -1
- django_smartbase_admin/engine/fake_inline.py +10 -0
- django_smartbase_admin/engine/field.py +13 -4
- django_smartbase_admin/static/sb_admin/dist/main.js +1 -1
- django_smartbase_admin/static/sb_admin/dist/main_style.css +1 -1
- django_smartbase_admin/static/sb_admin/images/file_types/file-doc.svg +11 -0
- django_smartbase_admin/static/sb_admin/images/file_types/file-xlsx.svg +11 -0
- django_smartbase_admin/static/sb_admin/src/js/main.js +29 -5
- django_smartbase_admin/templates/sb_admin/actions/change_form.html +90 -77
- django_smartbase_admin/templates/sb_admin/inlines/table_inline.html +1 -0
- django_smartbase_admin/templates/sb_admin/sb_admin_base.html +35 -3
- django_smartbase_admin/templates/sb_admin/widgets/clearable_file_input.html +2 -2
- django_smartbase_admin/templates/sb_admin/widgets/includes/related_item_buttons.html +2 -0
- django_smartbase_admin/templatetags/sb_admin_tags.py +40 -0
- {django_smartbase_admin-1.0.9.dist-info → django_smartbase_admin-1.0.11.dist-info}/METADATA +3 -1
- {django_smartbase_admin-1.0.9.dist-info → django_smartbase_admin-1.0.11.dist-info}/RECORD +20 -18
- {django_smartbase_admin-1.0.9.dist-info → django_smartbase_admin-1.0.11.dist-info}/LICENSE.md +0 -0
- {django_smartbase_admin-1.0.9.dist-info → django_smartbase_admin-1.0.11.dist-info}/WHEEL +0 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
1
2
|
import json
|
|
2
3
|
import math
|
|
4
|
+
from typing import Any, TYPE_CHECKING
|
|
3
5
|
|
|
4
|
-
from django.core.paginator import Paginator
|
|
5
6
|
from django.db.models import Q
|
|
6
7
|
from django.utils import timezone
|
|
7
8
|
from django.utils.html import escape
|
|
@@ -33,7 +34,6 @@ from django_smartbase_admin.engine.const import (
|
|
|
33
34
|
CONFIG_NAME,
|
|
34
35
|
TABLE_PARAMS_FULL_TEXT_SEARCH,
|
|
35
36
|
TABLE_PARAMS_SELECTED_FILTER_TYPE,
|
|
36
|
-
FilterVersions,
|
|
37
37
|
ADVANCED_FILTER_DATA_NAME,
|
|
38
38
|
IGNORE_LIST_SELECTION,
|
|
39
39
|
)
|
|
@@ -44,6 +44,9 @@ QueryBuilderService = import_with_injection(
|
|
|
44
44
|
"django_smartbase_admin.actions.advanced_filters", "QueryBuilderService"
|
|
45
45
|
)
|
|
46
46
|
|
|
47
|
+
if TYPE_CHECKING:
|
|
48
|
+
from django_smartbase_admin.engine.field import SBAdminField
|
|
49
|
+
|
|
47
50
|
|
|
48
51
|
class SBAdminAction(object):
|
|
49
52
|
view = None
|
|
@@ -289,7 +292,7 @@ class SBAdminListAction(SBAdminAction):
|
|
|
289
292
|
**self.get_annotates(visible_fields)
|
|
290
293
|
)
|
|
291
294
|
|
|
292
|
-
def get_visible_column_fields(self):
|
|
295
|
+
def get_visible_column_fields(self) -> list[SBAdminField]:
|
|
293
296
|
columns_data_dict = self.columns_data.get(COLUMNS_DATA_COLUMNS_NAME, {})
|
|
294
297
|
return [
|
|
295
298
|
field
|
|
@@ -407,14 +410,13 @@ class SBAdminListAction(SBAdminAction):
|
|
|
407
410
|
"last_row": total_count,
|
|
408
411
|
}
|
|
409
412
|
|
|
410
|
-
def process_final_data(self, final_data):
|
|
413
|
+
def process_final_data(self, final_data: list[dict[str, Any]]) -> None:
|
|
411
414
|
visible_columns = self.get_visible_column_fields()
|
|
412
|
-
|
|
413
|
-
field.field: field
|
|
414
|
-
for field in visible_columns
|
|
415
|
-
if field.view_method or field.python_formatter
|
|
415
|
+
field_key_field_map: dict[str, SBAdminField] = {
|
|
416
|
+
field.field: field for field in visible_columns
|
|
416
417
|
}
|
|
417
418
|
for row in final_data:
|
|
419
|
+
obj_id = row.get(self.get_pk_field().name, None)
|
|
418
420
|
additional_data = {}
|
|
419
421
|
if self.view.sbadmin_list_display_data:
|
|
420
422
|
additional_data = {
|
|
@@ -422,13 +424,11 @@ class SBAdminListAction(SBAdminAction):
|
|
|
422
424
|
for data in self.view.sbadmin_list_display_data
|
|
423
425
|
}
|
|
424
426
|
for field_key, value in row.items():
|
|
425
|
-
if field_key in
|
|
426
|
-
field =
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
if field.python_formatter:
|
|
431
|
-
value = field.python_formatter(object_id, value)
|
|
427
|
+
if field_key in field_key_field_map:
|
|
428
|
+
field = field_key_field_map[field_key]
|
|
429
|
+
value = self.view.process_field_data(
|
|
430
|
+
self.threadsafe_request, field, obj_id, value, additional_data
|
|
431
|
+
)
|
|
432
432
|
if isinstance(value, str) and not isinstance(value, SafeString):
|
|
433
433
|
value = escape(value)
|
|
434
434
|
row[field_key] = value
|
|
@@ -21,7 +21,7 @@ from django.core.exceptions import (
|
|
|
21
21
|
PermissionDenied,
|
|
22
22
|
)
|
|
23
23
|
from django.db import models
|
|
24
|
-
from django.db.models import QuerySet
|
|
24
|
+
from django.db.models import QuerySet, Q
|
|
25
25
|
from django.forms import HiddenInput
|
|
26
26
|
from django.forms.models import (
|
|
27
27
|
ModelFormMetaclass,
|
|
@@ -36,6 +36,7 @@ from django.utils.text import capfirst
|
|
|
36
36
|
from django.utils.translation import gettext_lazy as _
|
|
37
37
|
from django_admin_inline_paginator.admin import TabularInlinePaginated
|
|
38
38
|
from django_htmx.http import trigger_client_event
|
|
39
|
+
from django_smartbase_admin.engine.field import SBAdminField
|
|
39
40
|
from filer.fields.file import FilerFileField
|
|
40
41
|
from filer.fields.image import AdminImageFormField, FilerImageField
|
|
41
42
|
from nested_admin.formsets import NestedInlineFormSet
|
|
@@ -129,6 +130,7 @@ from django_smartbase_admin.engine.const import (
|
|
|
129
130
|
OBJECT_ID_PLACEHOLDER,
|
|
130
131
|
TRANSLATIONS_SELECTED_LANGUAGES,
|
|
131
132
|
ROW_CLASS_FIELD,
|
|
133
|
+
Action,
|
|
132
134
|
)
|
|
133
135
|
from django_smartbase_admin.services.translations import SBAdminTranslationsService
|
|
134
136
|
from django_smartbase_admin.services.views import SBAdminViewService
|
|
@@ -816,6 +818,9 @@ class SBAdmin(
|
|
|
816
818
|
def get_new_url(self, request) -> str:
|
|
817
819
|
return reverse(f"sb_admin:{self.get_id()}_add")
|
|
818
820
|
|
|
821
|
+
def get_additional_filter_for_previous_next_context(self, request, object_id) -> Q:
|
|
822
|
+
return Q()
|
|
823
|
+
|
|
819
824
|
def get_previous_next_context(self, request, object_id) -> dict | dict[str, Any]:
|
|
820
825
|
if not self.sbadmin_previous_next_buttons_enabled or not object_id:
|
|
821
826
|
return {}
|
|
@@ -831,14 +836,17 @@ class SBAdmin(
|
|
|
831
836
|
list_action = self.sbadmin_list_action_class(
|
|
832
837
|
self, request, all_params=all_params
|
|
833
838
|
)
|
|
839
|
+
additional_filter = self.get_additional_filter_for_previous_next_context(
|
|
840
|
+
request, object_id
|
|
841
|
+
)
|
|
834
842
|
all_ids = list(
|
|
835
|
-
list_action.build_final_data_count_queryset()
|
|
843
|
+
list_action.build_final_data_count_queryset(additional_filter)
|
|
836
844
|
.order_by(*list_action.get_order_by_from_request())
|
|
837
845
|
.values_list("id", flat=True)
|
|
838
846
|
)
|
|
839
847
|
index = all_ids.index(int(object_id))
|
|
840
|
-
previous_id =
|
|
841
|
-
next_id =
|
|
848
|
+
previous_id = all_ids[-1] if index == 0 else all_ids[index - 1]
|
|
849
|
+
next_id = all_ids[0] if index == len(all_ids) - 1 else all_ids[index + 1]
|
|
842
850
|
return {
|
|
843
851
|
"previous_url": (
|
|
844
852
|
f"{self.get_detail_url(previous_id)}?_changelist_filters={changelist_filters}"
|
|
@@ -982,6 +990,23 @@ class SBAdmin(
|
|
|
982
990
|
self.set_generic_relation_from_parent(request, obj)
|
|
983
991
|
super().save_model(request, obj, form, change)
|
|
984
992
|
|
|
993
|
+
def process_field_data(
|
|
994
|
+
self,
|
|
995
|
+
request,
|
|
996
|
+
field: SBAdminField,
|
|
997
|
+
obj_id: Any,
|
|
998
|
+
value: Any,
|
|
999
|
+
additional_data: dict[str, Any],
|
|
1000
|
+
) -> Any:
|
|
1001
|
+
is_xlsx_export = request.request_data.action == Action.XLSX_EXPORT.value
|
|
1002
|
+
if field.view_method:
|
|
1003
|
+
value = field.view_method(obj_id, value, **additional_data)
|
|
1004
|
+
if is_xlsx_export and getattr(field.xlsx_options, "python_formatter", None):
|
|
1005
|
+
value = field.xlsx_options.python_formatter(obj_id, value)
|
|
1006
|
+
elif field.python_formatter:
|
|
1007
|
+
value = field.python_formatter(obj_id, value)
|
|
1008
|
+
return value
|
|
1009
|
+
|
|
985
1010
|
|
|
986
1011
|
class SBAdminInline(
|
|
987
1012
|
SBAdminInlineAndAdminCommon, SBAdminBaseQuerysetMixin, SBAdminBaseView
|
|
@@ -31,7 +31,9 @@ from django_smartbase_admin.engine.filter_widgets import (
|
|
|
31
31
|
SBAdminTreeWidgetMixin,
|
|
32
32
|
)
|
|
33
33
|
from django_smartbase_admin.services.thread_local import SBAdminThreadLocalService
|
|
34
|
-
from django_smartbase_admin.templatetags.sb_admin_tags import
|
|
34
|
+
from django_smartbase_admin.templatetags.sb_admin_tags import (
|
|
35
|
+
SBAdminJSONEncoder,
|
|
36
|
+
)
|
|
35
37
|
from django_smartbase_admin.utils import is_modal
|
|
36
38
|
|
|
37
39
|
logger = logging.getLogger(__name__)
|
|
@@ -3,7 +3,9 @@ from django.db import models
|
|
|
3
3
|
from django.db.models import F
|
|
4
4
|
from django.forms import BaseInlineFormSet
|
|
5
5
|
|
|
6
|
+
from django_smartbase_admin.services.thread_local import SBAdminThreadLocalService
|
|
6
7
|
from django_smartbase_admin.services.views import SBAdminViewService
|
|
8
|
+
from django_smartbase_admin.utils import is_modal
|
|
7
9
|
|
|
8
10
|
|
|
9
11
|
class FakeQueryset(models.QuerySet):
|
|
@@ -33,6 +35,14 @@ class SBAdminFakeInlineFormset(BaseInlineFormSet):
|
|
|
33
35
|
original_model = None
|
|
34
36
|
inline_instance = None
|
|
35
37
|
|
|
38
|
+
@classmethod
|
|
39
|
+
def get_default_prefix(cls):
|
|
40
|
+
prefix = super().get_default_prefix()
|
|
41
|
+
modal_prefix = (
|
|
42
|
+
"modal_" if is_modal(SBAdminThreadLocalService.get_request()) else ""
|
|
43
|
+
)
|
|
44
|
+
return f"{modal_prefix}{prefix}"
|
|
45
|
+
|
|
36
46
|
def save_new(self, form, commit=True):
|
|
37
47
|
return self.inline_instance.save_new_fake_inline_instance(
|
|
38
48
|
form, self.inline_instance.parent_instance, commit
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
from collections.abc import Callable
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
1
4
|
from django.core.exceptions import FieldDoesNotExist, FieldError, ImproperlyConfigured
|
|
2
5
|
from django.db.models import (
|
|
3
6
|
Count,
|
|
@@ -52,17 +55,23 @@ class TabulatorFieldOptions(JSONSerializableMixin):
|
|
|
52
55
|
|
|
53
56
|
|
|
54
57
|
class XLSXFieldOptions(JSONSerializableMixin):
|
|
55
|
-
title = None
|
|
56
|
-
field = None
|
|
57
|
-
formatter = None
|
|
58
|
+
title: str | None = None
|
|
59
|
+
field: str | None = None
|
|
60
|
+
formatter: Formatter | None = None
|
|
61
|
+
python_formatter: Callable[[int, Any], Any] | None = None
|
|
58
62
|
|
|
59
63
|
def __init__(
|
|
60
|
-
self,
|
|
64
|
+
self,
|
|
65
|
+
title: str | None = None,
|
|
66
|
+
field: str | None = None,
|
|
67
|
+
formatter: Formatter | None = None,
|
|
68
|
+
python_formatter: Callable[[int, Any], Any] | None = None,
|
|
61
69
|
) -> None:
|
|
62
70
|
super().__init__()
|
|
63
71
|
self.title = title
|
|
64
72
|
self.field = field
|
|
65
73
|
self.formatter = formatter
|
|
74
|
+
self.python_formatter = python_formatter
|
|
66
75
|
|
|
67
76
|
|
|
68
77
|
class SBAdminField(JSONSerializableMixin):
|