django-smartbase-admin 0.2.73__py3-none-any.whl → 0.2.74__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 +10 -1
- django_smartbase_admin/admin/admin_base.py +17 -15
- django_smartbase_admin/admin/site.py +1 -2
- django_smartbase_admin/admin/widgets.py +15 -8
- django_smartbase_admin/engine/actions.py +20 -16
- django_smartbase_admin/engine/admin_base_view.py +47 -5
- django_smartbase_admin/engine/field.py +6 -1
- django_smartbase_admin/engine/modal_view.py +8 -4
- django_smartbase_admin/services/thread_local.py +6 -19
- django_smartbase_admin/services/views.py +47 -17
- django_smartbase_admin/templates/sb_admin/integrations/sorting/change_list.html +2 -2
- {django_smartbase_admin-0.2.73.dist-info → django_smartbase_admin-0.2.74.dist-info}/METADATA +1 -1
- {django_smartbase_admin-0.2.73.dist-info → django_smartbase_admin-0.2.74.dist-info}/RECORD +15 -15
- {django_smartbase_admin-0.2.73.dist-info → django_smartbase_admin-0.2.74.dist-info}/LICENSE.md +0 -0
- {django_smartbase_admin-0.2.73.dist-info → django_smartbase_admin-0.2.74.dist-info}/WHEEL +0 -0
|
@@ -6,7 +6,6 @@ from django.db.models import Q
|
|
|
6
6
|
from django.utils import timezone
|
|
7
7
|
from django.utils.text import smart_split, unescape_string_literal
|
|
8
8
|
|
|
9
|
-
from django_smartbase_admin.engine.actions import SBAdminAction
|
|
10
9
|
from django_smartbase_admin.engine.const import (
|
|
11
10
|
XLSX_PAGE_CHUNK_SIZE,
|
|
12
11
|
SELECTED_ROWS_KWARG_NAME,
|
|
@@ -43,6 +42,16 @@ QueryBuilderService = import_with_injection(
|
|
|
43
42
|
)
|
|
44
43
|
|
|
45
44
|
|
|
45
|
+
class SBAdminAction(object):
|
|
46
|
+
view = None
|
|
47
|
+
threadsafe_request = None
|
|
48
|
+
|
|
49
|
+
def __init__(self, view, request) -> None:
|
|
50
|
+
super().__init__()
|
|
51
|
+
self.view = view
|
|
52
|
+
self.threadsafe_request = request
|
|
53
|
+
|
|
54
|
+
|
|
46
55
|
class SBAdminListAction(SBAdminAction):
|
|
47
56
|
def __init__(
|
|
48
57
|
self,
|
|
@@ -37,6 +37,7 @@ from nested_admin.nested import (
|
|
|
37
37
|
|
|
38
38
|
from django_smartbase_admin.actions.admin_action_list import SBAdminListAction
|
|
39
39
|
from django_smartbase_admin.engine.actions import SBAdminCustomAction
|
|
40
|
+
from django_smartbase_admin.services.thread_local import SBAdminThreadLocalService
|
|
40
41
|
from django_smartbase_admin.utils import FormFieldsetMixin
|
|
41
42
|
|
|
42
43
|
parler_enabled = None
|
|
@@ -94,6 +95,7 @@ from django_smartbase_admin.admin.widgets import (
|
|
|
94
95
|
SBAdminHiddenWidget,
|
|
95
96
|
SBAdminCKEditorUploadingWidget,
|
|
96
97
|
SBAdminAttributesWidget,
|
|
98
|
+
SBAdminMultipleChoiceInlineWidget,
|
|
97
99
|
)
|
|
98
100
|
from django_smartbase_admin.engine.admin_base_view import (
|
|
99
101
|
SBAdminBaseListView,
|
|
@@ -132,6 +134,8 @@ class SBAdminFormFieldWidgetsMixin:
|
|
|
132
134
|
RichTextUploadingFormField: SBAdminCKEditorUploadingWidget,
|
|
133
135
|
forms.ChoiceField: SBAdminSelectWidget,
|
|
134
136
|
forms.TypedChoiceField: SBAdminSelectWidget,
|
|
137
|
+
forms.MultipleChoiceField: SBAdminMultipleChoiceInlineWidget,
|
|
138
|
+
forms.TypedMultipleChoiceField: SBAdminMultipleChoiceInlineWidget,
|
|
135
139
|
forms.NullBooleanField: SBAdminNullBooleanSelectWidget,
|
|
136
140
|
AdminImageFormField: SBAdminImageWidget,
|
|
137
141
|
ReadOnlyPasswordHashWidget: SBAdminReadOnlyPasswordHashWidget,
|
|
@@ -263,12 +267,13 @@ class SBAdminFormFieldWidgetsMixin:
|
|
|
263
267
|
|
|
264
268
|
|
|
265
269
|
class SBAdminBaseFormInit(SBAdminFormFieldWidgetsMixin, FormFieldsetMixin):
|
|
266
|
-
threadsafe_request = None
|
|
267
270
|
view = None
|
|
268
271
|
|
|
269
272
|
def __init__(self, *args, **kwargs):
|
|
270
273
|
self.view = kwargs.pop("view", self.view)
|
|
271
|
-
|
|
274
|
+
threadsafe_request = kwargs.pop(
|
|
275
|
+
"request", SBAdminThreadLocalService.get_request()
|
|
276
|
+
)
|
|
272
277
|
super().__init__(*args, **kwargs)
|
|
273
278
|
for field in self.fields:
|
|
274
279
|
if not hasattr(self.fields[field].widget, "init_widget_dynamic"):
|
|
@@ -278,14 +283,12 @@ class SBAdminBaseFormInit(SBAdminFormFieldWidgetsMixin, FormFieldsetMixin):
|
|
|
278
283
|
self.fields[field],
|
|
279
284
|
field,
|
|
280
285
|
self.view,
|
|
281
|
-
|
|
286
|
+
threadsafe_request,
|
|
282
287
|
)
|
|
283
288
|
for field in self.declared_fields:
|
|
284
289
|
form_field = self.fields.get(field)
|
|
285
290
|
if form_field:
|
|
286
|
-
self.assign_widget_to_form_field(
|
|
287
|
-
form_field, request=self.threadsafe_request
|
|
288
|
-
)
|
|
291
|
+
self.assign_widget_to_form_field(form_field, request=threadsafe_request)
|
|
289
292
|
|
|
290
293
|
|
|
291
294
|
class SBAdminBaseForm(SBAdminBaseFormInit, forms.ModelForm):
|
|
@@ -485,11 +488,6 @@ class SBAdminInlineAndAdminCommon(SBAdminFormFieldWidgetsMixin):
|
|
|
485
488
|
if form:
|
|
486
489
|
form.view = self
|
|
487
490
|
|
|
488
|
-
def initialize_form_class_threadsafe(self, form, request):
|
|
489
|
-
self.initialize_form_class(form)
|
|
490
|
-
if form:
|
|
491
|
-
form.threadsafe_request = request
|
|
492
|
-
|
|
493
491
|
|
|
494
492
|
class SBAdminThirdParty(SBAdminInlineAndAdminCommon, SBAdminBaseView):
|
|
495
493
|
def get_menu_view_url(self, request):
|
|
@@ -643,7 +641,7 @@ class SBAdmin(
|
|
|
643
641
|
|
|
644
642
|
def get_form(self, request, obj=None, **kwargs):
|
|
645
643
|
form = super().get_form(request, obj, **kwargs)
|
|
646
|
-
self.
|
|
644
|
+
self.initialize_form_class(form)
|
|
647
645
|
return form
|
|
648
646
|
|
|
649
647
|
def get_id(self):
|
|
@@ -705,7 +703,11 @@ class SBAdmin(
|
|
|
705
703
|
all_config = self.get_all_config(request)
|
|
706
704
|
url_suffix = ""
|
|
707
705
|
if all_config and all_config.get("all_params_changed", False):
|
|
708
|
-
url_params_dict =
|
|
706
|
+
url_params_dict = SBAdminViewService.process_url_params(
|
|
707
|
+
view_id=self.get_id(),
|
|
708
|
+
url_params=all_config.get("url_params"),
|
|
709
|
+
filter_version=self.get_filters_version(request),
|
|
710
|
+
)
|
|
709
711
|
if url_params_dict:
|
|
710
712
|
url_suffix = f"?{SBAdminViewService.build_list_url(self.get_id(), url_params_dict)}"
|
|
711
713
|
|
|
@@ -912,7 +914,7 @@ class SBAdminInline(
|
|
|
912
914
|
def register_autocomplete_views(self, request):
|
|
913
915
|
super().register_autocomplete_views(request)
|
|
914
916
|
form_class = self.get_formset(request, self.model()).form
|
|
915
|
-
self.
|
|
917
|
+
self.initialize_form_class(form_class)
|
|
916
918
|
form_class()
|
|
917
919
|
|
|
918
920
|
@property
|
|
@@ -956,7 +958,7 @@ class SBAdminInline(
|
|
|
956
958
|
def get_formset(self, request, obj=None, **kwargs):
|
|
957
959
|
formset = super().get_formset(request, obj, **kwargs)
|
|
958
960
|
form_class = formset.form
|
|
959
|
-
self.
|
|
961
|
+
self.initialize_form_class(form_class)
|
|
960
962
|
return formset
|
|
961
963
|
|
|
962
964
|
|
|
@@ -34,7 +34,7 @@ class SBAdminSite(admin.AdminSite):
|
|
|
34
34
|
request.sbadmin_selected_view = selected_view
|
|
35
35
|
kwargs["view"] = selected_view.get_id() if selected_view else None
|
|
36
36
|
request_data = SBAdminViewRequestData.from_request_and_kwargs(request, **kwargs)
|
|
37
|
-
SBAdminThreadLocalService.
|
|
37
|
+
SBAdminThreadLocalService.set_request(request)
|
|
38
38
|
if selected_view:
|
|
39
39
|
# Initialize SBAdmin, ModelAdmin instances, class-based SBAdminEntrypointView are initialized with request_data
|
|
40
40
|
selected_view.init_view_dynamic(
|
|
@@ -49,7 +49,6 @@ class SBAdminSite(admin.AdminSite):
|
|
|
49
49
|
response
|
|
50
50
|
)
|
|
51
51
|
|
|
52
|
-
SBAdminThreadLocalService.clear_data()
|
|
53
52
|
return response
|
|
54
53
|
|
|
55
54
|
def admin_view(self, view_function, cacheable=False):
|
|
@@ -16,6 +16,7 @@ from filer.fields.image import AdminImageWidget
|
|
|
16
16
|
from django_smartbase_admin.engine.filter_widgets import (
|
|
17
17
|
AutocompleteFilterWidget,
|
|
18
18
|
)
|
|
19
|
+
from django_smartbase_admin.services.thread_local import SBAdminThreadLocalService
|
|
19
20
|
from django_smartbase_admin.templatetags.sb_admin_tags import SBAdminJSONEncoder
|
|
20
21
|
|
|
21
22
|
|
|
@@ -277,7 +278,6 @@ class SBAdminAutocompleteWidget(
|
|
|
277
278
|
view = None
|
|
278
279
|
form = None
|
|
279
280
|
field_name = None
|
|
280
|
-
threadsafe_request = None
|
|
281
281
|
initialised = None
|
|
282
282
|
|
|
283
283
|
def __init__(self, form_field=None, *args, **kwargs):
|
|
@@ -285,6 +285,12 @@ class SBAdminAutocompleteWidget(
|
|
|
285
285
|
super().__init__(form_field, *args, **kwargs)
|
|
286
286
|
self.attrs = {} if attrs is None else attrs.copy()
|
|
287
287
|
|
|
288
|
+
def get_id(self):
|
|
289
|
+
base_id = super().get_id()
|
|
290
|
+
if self.form:
|
|
291
|
+
base_id += f"_{self.form.__class__.__name__}"
|
|
292
|
+
return base_id
|
|
293
|
+
|
|
288
294
|
def init_widget_dynamic(self, form, form_field, field_name, view, request):
|
|
289
295
|
super().init_widget_dynamic(form, form_field, field_name, view, request)
|
|
290
296
|
if self.initialised:
|
|
@@ -293,11 +299,10 @@ class SBAdminAutocompleteWidget(
|
|
|
293
299
|
self.field_name = field_name
|
|
294
300
|
self.view = view
|
|
295
301
|
self.form = form
|
|
296
|
-
self.threadsafe_request = request
|
|
297
302
|
self.init_autocomplete_widget_static(
|
|
298
303
|
self.field_name,
|
|
299
304
|
self.model,
|
|
300
|
-
|
|
305
|
+
request.request_data.configuration,
|
|
301
306
|
)
|
|
302
307
|
|
|
303
308
|
def get_field_name(self):
|
|
@@ -315,20 +320,21 @@ class SBAdminAutocompleteWidget(
|
|
|
315
320
|
getattr(self.form_field, "empty_label", "---------") or "---------"
|
|
316
321
|
)
|
|
317
322
|
query_suffix = "__in"
|
|
323
|
+
threadsafe_request = SBAdminThreadLocalService.get_request()
|
|
318
324
|
if not self.is_multiselect():
|
|
319
325
|
query_suffix = ""
|
|
320
326
|
self.multiselect = False
|
|
321
327
|
if value:
|
|
322
|
-
parsed_value = self.parse_value_from_input(
|
|
328
|
+
parsed_value = self.parse_value_from_input(threadsafe_request, value)
|
|
323
329
|
if parsed_value:
|
|
324
330
|
selected_options = []
|
|
325
|
-
for item in self.get_queryset(
|
|
331
|
+
for item in self.get_queryset(threadsafe_request).filter(
|
|
326
332
|
**{f"{self.get_value_field()}{query_suffix}": parsed_value}
|
|
327
333
|
):
|
|
328
334
|
selected_options.append(
|
|
329
335
|
{
|
|
330
|
-
"value": self.get_value(
|
|
331
|
-
"label": self.get_label(
|
|
336
|
+
"value": self.get_value(threadsafe_request, item),
|
|
337
|
+
"label": self.get_label(threadsafe_request, item),
|
|
332
338
|
}
|
|
333
339
|
)
|
|
334
340
|
context["widget"]["value"] = json.dumps(selected_options)
|
|
@@ -343,7 +349,8 @@ class SBAdminAutocompleteWidget(
|
|
|
343
349
|
|
|
344
350
|
def value_from_datadict(self, data, files, name):
|
|
345
351
|
input_value = super().value_from_datadict(data, files, name)
|
|
346
|
-
|
|
352
|
+
threadsafe_request = SBAdminThreadLocalService.get_request()
|
|
353
|
+
parsed_value = self.parse_value_from_input(threadsafe_request, input_value)
|
|
347
354
|
if parsed_value is None:
|
|
348
355
|
return parsed_value
|
|
349
356
|
return parsed_value if self.is_multiselect() else next(iter(parsed_value), None)
|
|
@@ -24,12 +24,6 @@ class SBAdminCustomAction(object):
|
|
|
24
24
|
group=None,
|
|
25
25
|
) -> None:
|
|
26
26
|
super().__init__()
|
|
27
|
-
|
|
28
|
-
if not (url or (view and action_id)):
|
|
29
|
-
raise ImproperlyConfigured(
|
|
30
|
-
"You must provide either url or view and action_id"
|
|
31
|
-
)
|
|
32
|
-
|
|
33
27
|
self.title = title
|
|
34
28
|
self.url = url
|
|
35
29
|
self.view = view
|
|
@@ -39,17 +33,27 @@ class SBAdminCustomAction(object):
|
|
|
39
33
|
self.no_params = no_params
|
|
40
34
|
self.open_in_modal = open_in_modal
|
|
41
35
|
self.group = group
|
|
42
|
-
|
|
36
|
+
self.resolve_url()
|
|
37
|
+
|
|
38
|
+
def resolve_url(self):
|
|
39
|
+
if not (self.url or (self.view and self.action_id)):
|
|
40
|
+
raise ImproperlyConfigured(
|
|
41
|
+
"You must provide either url or view and action_id"
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
if not self.url and not self.action_modifier:
|
|
43
45
|
self.url = self.view.get_action_url(self.action_id)
|
|
44
|
-
if not url and action_modifier is not None:
|
|
45
|
-
self.url = self.view.get_action_url(self.action_id, action_modifier)
|
|
46
|
+
if not self.url and self.action_modifier is not None:
|
|
47
|
+
self.url = self.view.get_action_url(self.action_id, self.action_modifier)
|
|
46
48
|
|
|
47
49
|
|
|
48
|
-
class
|
|
49
|
-
|
|
50
|
-
|
|
50
|
+
class SBAdminFormViewAction(SBAdminCustomAction):
|
|
51
|
+
def __init__(self, target_view, *args, **kwargs) -> None:
|
|
52
|
+
self.target_view = target_view
|
|
53
|
+
super().__init__(*args, **kwargs)
|
|
51
54
|
|
|
52
|
-
def
|
|
53
|
-
|
|
54
|
-
self.
|
|
55
|
-
|
|
55
|
+
def resolve_url(self):
|
|
56
|
+
"""
|
|
57
|
+
self.url and self.action_id is resolved in side django_smartbase_admin.engine.admin_base_view.SBAdminBaseView.process_actions
|
|
58
|
+
"""
|
|
59
|
+
pass
|
|
@@ -13,7 +13,10 @@ from django.urls import reverse
|
|
|
13
13
|
from django.utils.translation import gettext_lazy as _
|
|
14
14
|
|
|
15
15
|
from django_smartbase_admin.actions.admin_action_list import SBAdminListAction
|
|
16
|
-
from django_smartbase_admin.engine.actions import
|
|
16
|
+
from django_smartbase_admin.engine.actions import (
|
|
17
|
+
SBAdminCustomAction,
|
|
18
|
+
SBAdminFormViewAction,
|
|
19
|
+
)
|
|
17
20
|
from django_smartbase_admin.engine.const import (
|
|
18
21
|
Action,
|
|
19
22
|
OBJECT_ID_PLACEHOLDER,
|
|
@@ -28,6 +31,7 @@ from django_smartbase_admin.engine.const import (
|
|
|
28
31
|
BASE_PARAMS_NAME,
|
|
29
32
|
TABLE_RELOAD_DATA_EVENT_NAME,
|
|
30
33
|
TABLE_UPDATE_ROW_DATA_EVENT_NAME,
|
|
34
|
+
FILTER_DATA_NAME,
|
|
31
35
|
)
|
|
32
36
|
from django_smartbase_admin.services.views import SBAdminViewService
|
|
33
37
|
from django_smartbase_admin.services.xlsx_export import (
|
|
@@ -82,6 +86,27 @@ class SBAdminBaseView(object):
|
|
|
82
86
|
request, obj
|
|
83
87
|
)
|
|
84
88
|
|
|
89
|
+
def delegate_to_action_view(self, processed_action):
|
|
90
|
+
def inner_view(request, modifier):
|
|
91
|
+
return processed_action.target_view.as_view(view=self)(request)
|
|
92
|
+
|
|
93
|
+
return inner_view
|
|
94
|
+
|
|
95
|
+
def process_actions(self, request, actions):
|
|
96
|
+
processed_actions = self.process_actions_permissions(request, actions)
|
|
97
|
+
for processed_action in processed_actions:
|
|
98
|
+
if isinstance(processed_action, SBAdminFormViewAction):
|
|
99
|
+
action_id = processed_action.target_view.__name__
|
|
100
|
+
setattr(
|
|
101
|
+
self,
|
|
102
|
+
action_id,
|
|
103
|
+
self.delegate_to_action_view(processed_action),
|
|
104
|
+
)
|
|
105
|
+
processed_action.url = self.get_action_url(action_id)
|
|
106
|
+
processed_action.action_id = action_id
|
|
107
|
+
|
|
108
|
+
return processed_actions
|
|
109
|
+
|
|
85
110
|
def process_actions_permissions(self, request, actions):
|
|
86
111
|
result = []
|
|
87
112
|
for action in actions:
|
|
@@ -211,6 +236,7 @@ class SBAdminBaseListView(SBAdminBaseView):
|
|
|
211
236
|
sbadmin_list_reorder_field = None
|
|
212
237
|
search_field_placeholder = _("Search...")
|
|
213
238
|
filters_version = None
|
|
239
|
+
sbadmin_actions_initialized = False
|
|
214
240
|
sbadmin_list_action_class = SBAdminListAction
|
|
215
241
|
|
|
216
242
|
def activate_reorder(self, request):
|
|
@@ -297,11 +323,18 @@ class SBAdminBaseListView(SBAdminBaseView):
|
|
|
297
323
|
messages.add_message(request, messages.ERROR, "Not Implemented")
|
|
298
324
|
return HttpResponse(status=200, content=render_notifications(request))
|
|
299
325
|
|
|
326
|
+
def init_actions(self, request):
|
|
327
|
+
if self.sbadmin_actions_initialized:
|
|
328
|
+
return
|
|
329
|
+
self.process_actions(request, self.get_sbadmin_list_selection_actions())
|
|
330
|
+
self.sbadmin_actions_initialized = True
|
|
331
|
+
|
|
300
332
|
def init_view_dynamic(self, request, request_data=None, **kwargs):
|
|
301
333
|
super().init_view_dynamic(request, request_data, **kwargs)
|
|
302
334
|
self.init_fields_cache(
|
|
303
335
|
self.get_sbamin_list_display(request), request.request_data.configuration
|
|
304
336
|
)
|
|
337
|
+
self.init_actions(request)
|
|
305
338
|
|
|
306
339
|
def get_sbamin_list_display(self, request):
|
|
307
340
|
return self.sbadmin_list_display or self.list_display
|
|
@@ -313,6 +346,11 @@ class SBAdminBaseListView(SBAdminBaseView):
|
|
|
313
346
|
request.request_data.configuration,
|
|
314
347
|
force=True,
|
|
315
348
|
)
|
|
349
|
+
for list_action in self.get_sbadmin_list_selection_actions():
|
|
350
|
+
if isinstance(list_action, SBAdminFormViewAction):
|
|
351
|
+
form = list_action.target_view.form_class
|
|
352
|
+
form.view = self
|
|
353
|
+
form()
|
|
316
354
|
|
|
317
355
|
def get_list_display(self, request):
|
|
318
356
|
return [
|
|
@@ -453,7 +491,7 @@ class SBAdminBaseListView(SBAdminBaseView):
|
|
|
453
491
|
|
|
454
492
|
def get_sbadmin_list_selection_actions_grouped(self, request):
|
|
455
493
|
result = {}
|
|
456
|
-
list_selection_actions = self.
|
|
494
|
+
list_selection_actions = self.process_actions(
|
|
457
495
|
request, self.get_sbadmin_list_selection_actions()
|
|
458
496
|
)
|
|
459
497
|
for action in list_selection_actions:
|
|
@@ -607,6 +645,7 @@ class SBAdminBaseListView(SBAdminBaseView):
|
|
|
607
645
|
if not list_filter:
|
|
608
646
|
return all_config
|
|
609
647
|
list_fields = self.get_sbamin_list_display(request) or []
|
|
648
|
+
self.init_fields_cache(list_fields, request.request_data.configuration)
|
|
610
649
|
base_filter = {
|
|
611
650
|
getattr(field, "filter_field", field): ""
|
|
612
651
|
for field in list_fields
|
|
@@ -632,12 +671,15 @@ class SBAdminBaseListView(SBAdminBaseView):
|
|
|
632
671
|
list_view_config = [self.get_all_config(request), *sbadmin_list_config]
|
|
633
672
|
views = []
|
|
634
673
|
for defined_view in list_view_config:
|
|
674
|
+
url_params = SBAdminViewService.process_url_params(
|
|
675
|
+
view_id=self.get_id(),
|
|
676
|
+
url_params=defined_view["url_params"],
|
|
677
|
+
filter_version=self.get_filters_version(request),
|
|
678
|
+
)
|
|
635
679
|
views.append(
|
|
636
680
|
{
|
|
637
681
|
"name": defined_view["name"],
|
|
638
|
-
"url_params": SBAdminViewService.json_dumps_for_url(
|
|
639
|
-
defined_view["url_params"]
|
|
640
|
-
),
|
|
682
|
+
"url_params": SBAdminViewService.json_dumps_for_url(url_params),
|
|
641
683
|
"default": True,
|
|
642
684
|
}
|
|
643
685
|
)
|
|
@@ -83,6 +83,7 @@ class SBAdminField(JSONSerializableMixin):
|
|
|
83
83
|
python_formatter = None
|
|
84
84
|
tabulator_options = None
|
|
85
85
|
xlsx_options = None
|
|
86
|
+
initialized = False
|
|
86
87
|
|
|
87
88
|
def __init__(
|
|
88
89
|
self,
|
|
@@ -121,6 +122,7 @@ class SBAdminField(JSONSerializableMixin):
|
|
|
121
122
|
if (list_visible is not None)
|
|
122
123
|
else (self.list_visible if self.list_visible is not None else True)
|
|
123
124
|
)
|
|
125
|
+
self.list_visible_arg = list_visible
|
|
124
126
|
self.list_collapsed = list_collapsed or self.list_collapsed or False
|
|
125
127
|
self.auto_created = auto_created or self.auto_created or False
|
|
126
128
|
self.formatter = formatter
|
|
@@ -203,7 +205,9 @@ class SBAdminField(JSONSerializableMixin):
|
|
|
203
205
|
if self.model_field:
|
|
204
206
|
self.editable = self.model_field.editable
|
|
205
207
|
if self.model_field.is_relation:
|
|
206
|
-
self.list_visible =
|
|
208
|
+
self.list_visible = (
|
|
209
|
+
False if self.list_visible_arg is None else self.list_visible_arg
|
|
210
|
+
)
|
|
207
211
|
if self.model_field.auto_created:
|
|
208
212
|
self.detail_visible = False
|
|
209
213
|
self.title = self.title or getattr(
|
|
@@ -225,6 +229,7 @@ class SBAdminField(JSONSerializableMixin):
|
|
|
225
229
|
self.formatter = "html"
|
|
226
230
|
self.filter_field = self.filter_field or self.field
|
|
227
231
|
self.init_filter_for_field(configuration)
|
|
232
|
+
self.initialized = True
|
|
228
233
|
|
|
229
234
|
def serialize_tabulator(self):
|
|
230
235
|
data = {
|
|
@@ -28,11 +28,15 @@ class ActionModalView(FormView):
|
|
|
28
28
|
def get_form_class(self):
|
|
29
29
|
form_class = super().get_form_class()
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
fake_form_class = type(
|
|
32
|
+
form_class.__name__,
|
|
33
|
+
(form_class,),
|
|
34
|
+
{
|
|
35
|
+
"view": self.view,
|
|
36
|
+
},
|
|
37
|
+
)
|
|
34
38
|
|
|
35
|
-
return
|
|
39
|
+
return fake_form_class
|
|
36
40
|
|
|
37
41
|
def post(self, request, *args, **kwargs):
|
|
38
42
|
form = self.get_form()
|
|
@@ -1,26 +1,13 @@
|
|
|
1
|
-
from
|
|
1
|
+
from contextvars import ContextVar
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
sb_admin_request = ContextVar("sb_admin_request")
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class SBAdminThreadLocalService:
|
|
7
|
-
THREAD_DATA_KEY = "SB_ADMIN_DATA"
|
|
8
|
-
|
|
9
|
-
@classmethod
|
|
10
|
-
def get_wrapper(cls):
|
|
11
|
-
return getattr(_thread_locals, cls.THREAD_DATA_KEY, {})
|
|
12
|
-
|
|
13
|
-
@classmethod
|
|
14
|
-
def get_data(cls, key):
|
|
15
|
-
data_wrapper = cls.get_wrapper()
|
|
16
|
-
return data_wrapper.get(key)
|
|
17
|
-
|
|
18
7
|
@classmethod
|
|
19
|
-
def
|
|
20
|
-
|
|
21
|
-
data_wrapper[key] = data
|
|
8
|
+
def get_request(cls):
|
|
9
|
+
return sb_admin_request.get()
|
|
22
10
|
|
|
23
11
|
@classmethod
|
|
24
|
-
def
|
|
25
|
-
|
|
26
|
-
delattr(_thread_locals, cls.THREAD_DATA_KEY)
|
|
12
|
+
def set_request(cls, request):
|
|
13
|
+
sb_admin_request.set(request)
|
|
@@ -4,6 +4,7 @@ import urllib
|
|
|
4
4
|
|
|
5
5
|
from django.db.models import Q, FilteredRelation, F, Value, CharField
|
|
6
6
|
from django.shortcuts import redirect
|
|
7
|
+
from django_smartbase_admin.templatetags.sb_admin_tags import SBAdminJSONEncoder
|
|
7
8
|
|
|
8
9
|
from django_smartbase_admin.engine.const import (
|
|
9
10
|
BASE_PARAMS_NAME,
|
|
@@ -20,17 +21,52 @@ from django_smartbase_admin.services.translations import SBAdminTranslationsServ
|
|
|
20
21
|
class SBAdminViewService(object):
|
|
21
22
|
@classmethod
|
|
22
23
|
def json_dumps_for_url(cls, data):
|
|
23
|
-
return json.dumps(data, separators=(",", ":"))
|
|
24
|
+
return json.dumps(data, separators=(",", ":"), cls=SBAdminJSONEncoder)
|
|
24
25
|
|
|
25
26
|
@classmethod
|
|
26
27
|
def json_dumps_and_replace(cls, data):
|
|
27
|
-
return cls.json_dumps_for_url(data)
|
|
28
|
+
return cls.json_dumps_for_url(data)
|
|
28
29
|
|
|
29
30
|
@classmethod
|
|
30
31
|
def build_list_url(cls, view_id, url_params):
|
|
31
32
|
params = {view_id: url_params}
|
|
32
33
|
return f"{BASE_PARAMS_NAME}={cls.json_dumps_for_url(params)}"
|
|
33
34
|
|
|
35
|
+
@classmethod
|
|
36
|
+
def process_url_params(cls, view_id, url_params, filter_version):
|
|
37
|
+
filter_data = SBAdminViewService.process_filter_data_url(
|
|
38
|
+
view_id=view_id,
|
|
39
|
+
filter_data=url_params.get(FILTER_DATA_NAME, {}),
|
|
40
|
+
filter_version=filter_version,
|
|
41
|
+
)
|
|
42
|
+
url_params_processed = {**url_params}
|
|
43
|
+
if filter_data:
|
|
44
|
+
url_params_processed[FILTER_DATA_NAME] = filter_data
|
|
45
|
+
return url_params_processed
|
|
46
|
+
|
|
47
|
+
@classmethod
|
|
48
|
+
def process_filter_data_url(cls, view_id, filter_data, filter_version):
|
|
49
|
+
if filter_version == FilterVersions.FILTERS_VERSION_2:
|
|
50
|
+
filter_data_processed = []
|
|
51
|
+
for key, value in filter_data.items():
|
|
52
|
+
filter_value = {
|
|
53
|
+
"id": f"{view_id}-{key}",
|
|
54
|
+
"field": key,
|
|
55
|
+
"type": "string",
|
|
56
|
+
"input": "text",
|
|
57
|
+
"operator": "contains",
|
|
58
|
+
}
|
|
59
|
+
filter_value.update(value)
|
|
60
|
+
filter_data_processed.append(filter_value)
|
|
61
|
+
return filter_data_processed
|
|
62
|
+
else:
|
|
63
|
+
filter_data_processed = {}
|
|
64
|
+
for filter_key, filter_value in filter_data.items():
|
|
65
|
+
filter_data_processed[filter_key] = cls.json_dumps_and_replace(
|
|
66
|
+
filter_value
|
|
67
|
+
)
|
|
68
|
+
return filter_data_processed
|
|
69
|
+
|
|
34
70
|
@classmethod
|
|
35
71
|
def build_list_params_url(cls, view_id, filter_data=None, filter_version=None):
|
|
36
72
|
if filter_version == FilterVersions.FILTERS_VERSION_2:
|
|
@@ -44,24 +80,18 @@ class SBAdminViewService(object):
|
|
|
44
80
|
TABLE_PARAMS_SELECTED_FILTER_TYPE: TABLE_TAB_ADVANCED_FITLERS
|
|
45
81
|
},
|
|
46
82
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
"field": key,
|
|
51
|
-
"type": "string",
|
|
52
|
-
"input": "text",
|
|
53
|
-
"operator": "contains",
|
|
54
|
-
}
|
|
55
|
-
filter_value.update(value)
|
|
56
|
-
filter_dict[ADVANCED_FILTER_DATA_NAME]["rules"].append(filter_value)
|
|
83
|
+
filter_dict[ADVANCED_FILTER_DATA_NAME]["rules"].extend(
|
|
84
|
+
cls.process_filter_data_url(view_id, filter_data, filter_version)
|
|
85
|
+
)
|
|
57
86
|
params = {BASE_PARAMS_NAME: cls.json_dumps_for_url({view_id: filter_dict})}
|
|
58
87
|
return urllib.parse.urlencode(params)
|
|
59
88
|
filter_data = filter_data or {}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
89
|
+
view_params = {
|
|
90
|
+
FILTER_DATA_NAME: cls.process_filter_data_url(
|
|
91
|
+
view_id, filter_data, filter_version
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
return cls.build_list_url(view_id, view_params)
|
|
65
95
|
|
|
66
96
|
@classmethod
|
|
67
97
|
def get_pk_field_for_model(cls, model):
|
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
django_smartbase_admin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
2
|
django_smartbase_admin/actions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
django_smartbase_admin/actions/admin_action_list.py,sha256=
|
|
3
|
+
django_smartbase_admin/actions/admin_action_list.py,sha256=EWk0KTXDVVJDT8bh052xazukTpYFFOzrKTp36m1QNzE,19229
|
|
4
4
|
django_smartbase_admin/actions/advanced_filters.py,sha256=Vm8b6TAwNehR8INjolFG7pEYL4ADO7XUiVOWpb0btM0,13481
|
|
5
5
|
django_smartbase_admin/admin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
-
django_smartbase_admin/admin/admin_base.py,sha256=
|
|
7
|
-
django_smartbase_admin/admin/site.py,sha256=
|
|
8
|
-
django_smartbase_admin/admin/widgets.py,sha256=
|
|
6
|
+
django_smartbase_admin/admin/admin_base.py,sha256=9fN3c41fNkav7uQiGfEnJaiqYKfDk57VrlYgiN04DE8,40100
|
|
7
|
+
django_smartbase_admin/admin/site.py,sha256=VrJBhwgZsLa2GohvjnNL7m4dVR3S4Ou1V1UzfE1qOoQ,6577
|
|
8
|
+
django_smartbase_admin/admin/widgets.py,sha256=udNG3fqDSTKnbPpvY02qhanPoCm_Kgn7Bg8R3EjWJT4,15035
|
|
9
9
|
django_smartbase_admin/apps.py,sha256=3Wm88v1u-ejKVSRsdgsnOrjOfdlsp1qVULskabgH1iY,479
|
|
10
10
|
django_smartbase_admin/compilemessages.py,sha256=-_FEFQlOvE4L8UzSuUxSxZQjgGlwL9IZtmg59fW_kIQ,342
|
|
11
11
|
django_smartbase_admin/engine/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
|
-
django_smartbase_admin/engine/actions.py,sha256=
|
|
13
|
-
django_smartbase_admin/engine/admin_base_view.py,sha256
|
|
12
|
+
django_smartbase_admin/engine/actions.py,sha256=n8PiG60Kj1ECHB4lfVH_jvHMyOjOZ-DvQfO9F2CuqW0,1733
|
|
13
|
+
django_smartbase_admin/engine/admin_base_view.py,sha256=ni1UV_nc_oeccRhKi9nyy520QB18nhZnmmcdaAIE6Hs,28475
|
|
14
14
|
django_smartbase_admin/engine/admin_entrypoint_view.py,sha256=jfMfcYPfdre2abHfC4KIxaP_epJFuCeTcujGhGd4Tl4,624
|
|
15
15
|
django_smartbase_admin/engine/admin_view.py,sha256=9wGffahDR3IYmhL9ZbX8uitwGdXdw5DIL5GnWBawmJM,4238
|
|
16
16
|
django_smartbase_admin/engine/configuration.py,sha256=P3iSiPm9QBl9etTDJIWzo7DzOBCryGwWtbF288PEtus,8120
|
|
17
17
|
django_smartbase_admin/engine/const.py,sha256=vU_XMy76BYiw1tu88lw8UDGk-cW5oo62gh9mT36_2tk,2437
|
|
18
18
|
django_smartbase_admin/engine/dashboard.py,sha256=wrvX0GI-SII2pG0DX8Kvy4JFaM6h8e6R7KSCFddFC64,23642
|
|
19
19
|
django_smartbase_admin/engine/fake_inline.py,sha256=9C2_mltg2P9-xa3vuoo5X_RcFaCRpKGNSy7t1_iiasE,5802
|
|
20
|
-
django_smartbase_admin/engine/field.py,sha256=
|
|
20
|
+
django_smartbase_admin/engine/field.py,sha256=BD_W0ekE5tQJxUGpUA8bo4ZyFk0u2F_6UTPH4drj0JU,10286
|
|
21
21
|
django_smartbase_admin/engine/field_formatter.py,sha256=GzyvcBr8Cru34yMedd1GYOl2jTTopEGeSEhoM9_CfKQ,1754
|
|
22
22
|
django_smartbase_admin/engine/filter_widgets.py,sha256=lHPMilA2tjtwnwqPw2nUE39BL1Dx_v4HNKhmg6szHUY,23687
|
|
23
23
|
django_smartbase_admin/engine/global_filter_form.py,sha256=jlj6e9VYWDPyUNjcgj3gTIkCZXO01NZOWAeU3jFtkoA,249
|
|
24
24
|
django_smartbase_admin/engine/menu_item.py,sha256=rMJFG5xm1T0wF8lUmiAZHzKtt9C0LdbpRFvaP0PlngM,2936
|
|
25
|
-
django_smartbase_admin/engine/modal_view.py,sha256=
|
|
25
|
+
django_smartbase_admin/engine/modal_view.py,sha256=6eAmncDV9UzTWemWFQXZpVCIixWo5gWvNZGnK4mw4FM,2251
|
|
26
26
|
django_smartbase_admin/engine/request.py,sha256=sFjxgmzGXUeCD3hEx-Eu-ebgF8CnrBJDH2e8LF1ieRg,2615
|
|
27
27
|
django_smartbase_admin/integration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
28
28
|
django_smartbase_admin/integration/django_cms.py,sha256=asLVmQUDHulGEpkqp5cUv6-aTcZPoeOllPE1_AIWUqM,1062
|
|
@@ -40,9 +40,9 @@ django_smartbase_admin/querysets.py,sha256=ST_6qxznqxJiv8Gk1bgYVMpK_gbU74ItKyvMm
|
|
|
40
40
|
django_smartbase_admin/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
41
41
|
django_smartbase_admin/services/configuration.py,sha256=POMI0htBqFS9ptPXMtOhIlIKiF6Y4cOQ-IkYN6NWO1c,759
|
|
42
42
|
django_smartbase_admin/services/data.py,sha256=o36B_H9RnBvaQz3Rs3NygY1hVTr6hc89M-RK1saRXzc,156
|
|
43
|
-
django_smartbase_admin/services/thread_local.py,sha256=
|
|
43
|
+
django_smartbase_admin/services/thread_local.py,sha256=C3x7hPsKRCddr05RGiN0f6fcSQ8qsrYRdx9oeMHRovU,293
|
|
44
44
|
django_smartbase_admin/services/translations.py,sha256=aiekREx8KQA9CQRmtkUcys4ICJERMrkxPnLysp0YXO8,5606
|
|
45
|
-
django_smartbase_admin/services/views.py,sha256=
|
|
45
|
+
django_smartbase_admin/services/views.py,sha256=oTZXHvZl-eGCaHRoQiEG-YLKAGGs3FcuVDZhdiuuv34,8953
|
|
46
46
|
django_smartbase_admin/services/xlsx_export.py,sha256=fnIqahmZR6G5T5wSH-sXhhLSy1QD3A-OY6BAn1WLLOc,10723
|
|
47
47
|
django_smartbase_admin/static/sb_admin/build/postcss.config.js,sha256=JlIB66vejH4YA3sPp7hDjimQXAGz5WlVhFDwjBDNTEo,610
|
|
48
48
|
django_smartbase_admin/static/sb_admin/build/tailwind.config.js,sha256=5q5CGlXyn5s3hB6k2OCTu4auVcY4_yop5TrM5g0pT80,2369
|
|
@@ -593,7 +593,7 @@ django_smartbase_admin/templates/sb_admin/integrations/cms/translations_status_r
|
|
|
593
593
|
django_smartbase_admin/templates/sb_admin/integrations/filer/filer_change_form.html,sha256=ts8H3F-0VVhxuJfgmPiMo5rGwub5pLzhUx513kw_zVE,3002
|
|
594
594
|
django_smartbase_admin/templates/sb_admin/integrations/filer/folder_list.html,sha256=Z5dZRNprEslkBDwYE3u8brVNt9qOhLX1gYG8wWjVGk8,18834
|
|
595
595
|
django_smartbase_admin/templates/sb_admin/integrations/filer/image_change_form.html,sha256=CESQuiGfbKdMEq9DRIXfOS-jpz8yr64TJ7R_cs6jZ9M,1909
|
|
596
|
-
django_smartbase_admin/templates/sb_admin/integrations/sorting/change_list.html,sha256=
|
|
596
|
+
django_smartbase_admin/templates/sb_admin/integrations/sorting/change_list.html,sha256=2TSTiKZ52Gpp_Jf5EHr4BEUxnxVXdEY9jEHrtn2f5Xc,15190
|
|
597
597
|
django_smartbase_admin/templates/sb_admin/navigation.html,sha256=jU7aeGihp_oxhGHjVo_j5j7g03z-EPzYPk9PHt5NSFE,10613
|
|
598
598
|
django_smartbase_admin/templates/sb_admin/partials/messages/alert_base.html,sha256=F61XeaBMR7YL9wx0VDXdJ9uTlBMNGSMsXmk6IHZuuNk,825
|
|
599
599
|
django_smartbase_admin/templates/sb_admin/partials/messages/alert_close.html,sha256=-BhLje6G4Ey36hOseZ41WxjmdsMeCOza_2okBn0EWiM,121
|
|
@@ -658,7 +658,7 @@ django_smartbase_admin/views/dashboard_view.py,sha256=vtz5emYTQ5WDFeLA8HrcmjSOVd
|
|
|
658
658
|
django_smartbase_admin/views/global_filter_view.py,sha256=eYo1moJGyi7jc2cPDA5ZBiEgA7Hmc-DxbQvbqUpDkg8,1127
|
|
659
659
|
django_smartbase_admin/views/media_view.py,sha256=5BLWXuzynF7nM34t-mf2BQSRN5ojY8HxpLIqt7Jiq9g,292
|
|
660
660
|
django_smartbase_admin/views/translations_view.py,sha256=A02q1t13akLKd2Pg_ej4tVi5qPUKYxB2LqsBbYXM0l8,20267
|
|
661
|
-
django_smartbase_admin-0.2.
|
|
662
|
-
django_smartbase_admin-0.2.
|
|
663
|
-
django_smartbase_admin-0.2.
|
|
664
|
-
django_smartbase_admin-0.2.
|
|
661
|
+
django_smartbase_admin-0.2.74.dist-info/LICENSE.md,sha256=okRGMBOYvyhprt2eTpX_QXqpzC0MODF-U7zX-4fKPjQ,1078
|
|
662
|
+
django_smartbase_admin-0.2.74.dist-info/METADATA,sha256=iqrHWxzbyeBME7JNoGboxqWBnJX5U7EyyMCWhQ36bbk,945
|
|
663
|
+
django_smartbase_admin-0.2.74.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
664
|
+
django_smartbase_admin-0.2.74.dist-info/RECORD,,
|
{django_smartbase_admin-0.2.73.dist-info → django_smartbase_admin-0.2.74.dist-info}/LICENSE.md
RENAMED
|
File without changes
|
|
File without changes
|