fastadmin 0.4.4__tar.gz → 0.4.6__tar.gz
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.
- {fastadmin-0.4.4 → fastadmin-0.4.6}/PKG-INFO +1 -1
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/__init__.py +2 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/models/base.py +10 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/models/decorators.py +41 -15
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/models/helpers.py +5 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/models/schemas.py +14 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/static/index.min.js +165 -165
- {fastadmin-0.4.4 → fastadmin-0.4.6}/pyproject.toml +1 -1
- {fastadmin-0.4.4 → fastadmin-0.4.6}/LICENSE +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/README.md +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/api/__init__.py +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/api/exceptions.py +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/api/frameworks/__init__.py +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/api/frameworks/django/__init__.py +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/api/frameworks/django/app/__init__.py +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/api/frameworks/django/app/api.py +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/api/frameworks/django/app/urls.py +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/api/frameworks/django/app/views.py +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/api/frameworks/fastapi/__init__.py +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/api/frameworks/fastapi/api.py +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/api/frameworks/fastapi/app.py +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/api/frameworks/fastapi/views.py +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/api/frameworks/flask/__init__.py +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/api/frameworks/flask/api.py +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/api/frameworks/flask/app.py +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/api/frameworks/flask/views.py +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/api/helpers.py +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/api/schemas.py +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/api/service.py +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/models/__init__.py +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/models/orms/__init__.py +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/models/orms/django.py +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/models/orms/ponyorm.py +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/models/orms/sqlalchemy.py +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/models/orms/tortoise.py +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/settings.py +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/static/assets/worker-6Z7niv9l.js +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/static/assets/worker-C151k0-L.js +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/static/assets/worker-C9KPOOKD.js +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/static/assets/worker-D1fCgYB7.js +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/static/assets/worker-D3TWcJOI.js +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/static/assets/worker-DRNcaZ-V.js +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/static/assets/worker-MF2p-l5_.js +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/static/images/favicon.png +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/static/images/header-logo.svg +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/static/images/sign-in-logo.svg +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/static/index.html +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/static/index.min.css +0 -0
- {fastadmin-0.4.4 → fastadmin-0.4.6}/fastadmin/templates/index.html +0 -0
|
@@ -43,10 +43,12 @@ from fastadmin.models.schemas import ( # noqa: F401
|
|
|
43
43
|
ActionInputSchema,
|
|
44
44
|
ActionResponseSchema,
|
|
45
45
|
ActionResponseType,
|
|
46
|
+
ModelWidgetAction,
|
|
46
47
|
WidgetActionArgumentProps,
|
|
47
48
|
WidgetActionChartProps,
|
|
48
49
|
WidgetActionFilter,
|
|
49
50
|
WidgetActionInputSchema,
|
|
51
|
+
WidgetActionParentArgumentProps,
|
|
50
52
|
WidgetActionProps,
|
|
51
53
|
WidgetActionQuerySchema,
|
|
52
54
|
WidgetActionResponseSchema,
|
|
@@ -243,6 +243,12 @@ class BaseModelAdmin:
|
|
|
243
243
|
"""
|
|
244
244
|
raise NotImplementedError
|
|
245
245
|
|
|
246
|
+
async def pre_generate_models_schema(self) -> None:
|
|
247
|
+
"""This method is used to pre-generate models schema.
|
|
248
|
+
|
|
249
|
+
:return: None.
|
|
250
|
+
"""
|
|
251
|
+
|
|
246
252
|
async def orm_get_list(
|
|
247
253
|
self,
|
|
248
254
|
offset: int | None = None,
|
|
@@ -660,6 +666,10 @@ class InlineModelAdmin(BaseModelAdmin):
|
|
|
660
666
|
class ModelAdmin(BaseModelAdmin):
|
|
661
667
|
"""This class is used to create admin model class."""
|
|
662
668
|
|
|
669
|
+
# Optional section name for grouping models in the left menu.
|
|
670
|
+
# Example of usage: menu_section = "Users"
|
|
671
|
+
menu_section: str | None = None
|
|
672
|
+
|
|
663
673
|
# Normally, objects have three save options: “Save”, “Save and continue editing”, and “Save and add another”.
|
|
664
674
|
# If save_as is True, “Save and add another” will be replaced
|
|
665
675
|
# by a “Save as new” button that creates a new object (with a new ID) rather than updating the existing object.
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import typing as tp
|
|
2
|
+
from functools import wraps
|
|
3
|
+
from inspect import iscoroutinefunction
|
|
2
4
|
|
|
3
5
|
from fastadmin.models.schemas import (
|
|
4
6
|
WidgetActionChartProps,
|
|
@@ -8,6 +10,22 @@ from fastadmin.models.schemas import (
|
|
|
8
10
|
)
|
|
9
11
|
|
|
10
12
|
|
|
13
|
+
def _wrap_callable(func):
|
|
14
|
+
if iscoroutinefunction(func):
|
|
15
|
+
|
|
16
|
+
@wraps(func)
|
|
17
|
+
async def wrapped(*args, **kwargs):
|
|
18
|
+
return await func(*args, **kwargs)
|
|
19
|
+
|
|
20
|
+
else:
|
|
21
|
+
|
|
22
|
+
@wraps(func)
|
|
23
|
+
def wrapped(*args, **kwargs):
|
|
24
|
+
return func(*args, **kwargs)
|
|
25
|
+
|
|
26
|
+
return wrapped
|
|
27
|
+
|
|
28
|
+
|
|
11
29
|
def action(
|
|
12
30
|
function=None,
|
|
13
31
|
*,
|
|
@@ -27,10 +45,12 @@ def action(
|
|
|
27
45
|
"""
|
|
28
46
|
|
|
29
47
|
def decorator(func):
|
|
30
|
-
|
|
48
|
+
wrapped = _wrap_callable(func)
|
|
49
|
+
|
|
50
|
+
wrapped.is_action = True
|
|
31
51
|
if description is not None:
|
|
32
|
-
|
|
33
|
-
return
|
|
52
|
+
wrapped.short_description = description
|
|
53
|
+
return wrapped
|
|
34
54
|
|
|
35
55
|
if function is None:
|
|
36
56
|
return decorator
|
|
@@ -49,6 +69,7 @@ def widget_action(
|
|
|
49
69
|
width: (
|
|
50
70
|
tp.Literal[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24] | None
|
|
51
71
|
) = None, # width in 1-24 grid system
|
|
72
|
+
max_height: int | None = None,
|
|
52
73
|
):
|
|
53
74
|
"""Conveniently add attributes to a widget action function:
|
|
54
75
|
|
|
@@ -103,16 +124,19 @@ def widget_action(
|
|
|
103
124
|
"""
|
|
104
125
|
|
|
105
126
|
def decorator(func):
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
127
|
+
wrapped = _wrap_callable(func)
|
|
128
|
+
|
|
129
|
+
wrapped.is_widget_action = True
|
|
130
|
+
wrapped.widget_action_type = widget_action_type
|
|
131
|
+
wrapped.widget_action_props = widget_action_props
|
|
132
|
+
wrapped.widget_action_filters = widget_action_filters
|
|
133
|
+
wrapped.tab = tab
|
|
134
|
+
wrapped.title = title
|
|
135
|
+
wrapped.width = width
|
|
136
|
+
wrapped.max_height = max_height
|
|
113
137
|
if description is not None:
|
|
114
|
-
|
|
115
|
-
return
|
|
138
|
+
wrapped.short_description = description
|
|
139
|
+
return wrapped
|
|
116
140
|
|
|
117
141
|
if function is None:
|
|
118
142
|
return decorator
|
|
@@ -137,9 +161,11 @@ def display(function=None, *, sorter: bool | str = False):
|
|
|
137
161
|
"""
|
|
138
162
|
|
|
139
163
|
def decorator(func):
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
164
|
+
wrapped = _wrap_callable(func)
|
|
165
|
+
|
|
166
|
+
wrapped.is_display = True
|
|
167
|
+
wrapped.sorter = sorter
|
|
168
|
+
return wrapped
|
|
143
169
|
|
|
144
170
|
if function is None:
|
|
145
171
|
return decorator
|
|
@@ -115,6 +115,9 @@ async def generate_models_schema(
|
|
|
115
115
|
for orm_model_cls, admin_model_obj in admin_models.items():
|
|
116
116
|
if hasattr(admin_model_obj, "set_context"):
|
|
117
117
|
admin_model_obj.set_context(request=request, user=user)
|
|
118
|
+
pre_generate_models_schema = getattr(admin_model_obj, "pre_generate_models_schema", None)
|
|
119
|
+
if callable(pre_generate_models_schema):
|
|
120
|
+
await pre_generate_models_schema()
|
|
118
121
|
orm_model_fields = admin_model_obj.get_model_fields_with_widget_types()
|
|
119
122
|
orm_model_fields_for_serialize = admin_model_obj.get_fields_for_serialize()
|
|
120
123
|
|
|
@@ -242,6 +245,7 @@ async def generate_models_schema(
|
|
|
242
245
|
title=widget_action_function.title,
|
|
243
246
|
tab=widget_action_function.tab,
|
|
244
247
|
width=widget_action_function.width,
|
|
248
|
+
max_height=getattr(widget_action_function, "max_height", None),
|
|
245
249
|
description=getattr(widget_action_function, "short_description", None),
|
|
246
250
|
widget_action_type=widget_action_function.widget_action_type,
|
|
247
251
|
widget_action_props=widget_action_function.widget_action_props,
|
|
@@ -272,6 +276,7 @@ async def generate_models_schema(
|
|
|
272
276
|
show_full_result_count=admin_model_obj.show_full_result_count,
|
|
273
277
|
verbose_name=admin_model_obj.verbose_name,
|
|
274
278
|
verbose_name_plural=admin_model_obj.verbose_name_plural,
|
|
279
|
+
menu_section=getattr(admin_model_obj, "menu_section", None),
|
|
275
280
|
# specific model fields
|
|
276
281
|
fieldsets=admin_model_obj.fieldsets,
|
|
277
282
|
save_on_top=admin_model_obj.save_on_top,
|
|
@@ -70,6 +70,14 @@ class WidgetActionChartProps:
|
|
|
70
70
|
series_color: list[str] | dict[str, str] | None = None
|
|
71
71
|
|
|
72
72
|
|
|
73
|
+
@dataclass
|
|
74
|
+
class WidgetActionParentArgumentProps:
|
|
75
|
+
"""Widget action parent argument props"""
|
|
76
|
+
|
|
77
|
+
name: str
|
|
78
|
+
value: tp.Any
|
|
79
|
+
|
|
80
|
+
|
|
73
81
|
@dataclass
|
|
74
82
|
class WidgetActionArgumentProps:
|
|
75
83
|
"""Widget action chart props"""
|
|
@@ -78,6 +86,10 @@ class WidgetActionArgumentProps:
|
|
|
78
86
|
widget_type: WidgetType
|
|
79
87
|
widget_props: dict | None = None
|
|
80
88
|
|
|
89
|
+
# if None, show always
|
|
90
|
+
# if not None, show only if parent selected/input value is equal to the parent_argument.value
|
|
91
|
+
parent_argument: WidgetActionParentArgumentProps | None = None
|
|
92
|
+
|
|
81
93
|
|
|
82
94
|
@dataclass
|
|
83
95
|
class WidgetActionProps:
|
|
@@ -112,6 +124,7 @@ class ModelWidgetAction:
|
|
|
112
124
|
description: str | None
|
|
113
125
|
tab: str
|
|
114
126
|
width: int | None
|
|
127
|
+
max_height: int | None
|
|
115
128
|
widget_action_type: WidgetActionType
|
|
116
129
|
widget_action_props: WidgetActionChartProps | WidgetActionProps | None = None
|
|
117
130
|
widget_action_filters: list[WidgetActionFilter] | None = None
|
|
@@ -199,6 +212,7 @@ class InlineModelSchema(BaseModelSchema):
|
|
|
199
212
|
class ModelSchema(BaseModelSchema):
|
|
200
213
|
"""Model schema"""
|
|
201
214
|
|
|
215
|
+
menu_section: str | None
|
|
202
216
|
fieldsets: Sequence[tuple[str | None, dict[str, Sequence[str]]]] | None
|
|
203
217
|
save_on_top: bool | None
|
|
204
218
|
save_as: bool | None
|