fastadmin 0.2.8__py3-none-any.whl → 0.2.10__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.
- fastadmin/api/service.py +2 -1
- fastadmin/models/orms/django.py +0 -2
- fastadmin/models/orms/ponyorm.py +12 -8
- fastadmin/models/orms/sqlalchemy.py +2 -1
- fastadmin/models/orms/tortoise.py +13 -8
- fastadmin/static/index.min.js +53 -53
- {fastadmin-0.2.8.dist-info → fastadmin-0.2.10.dist-info}/METADATA +1 -1
- {fastadmin-0.2.8.dist-info → fastadmin-0.2.10.dist-info}/RECORD +10 -10
- {fastadmin-0.2.8.dist-info → fastadmin-0.2.10.dist-info}/LICENSE +0 -0
- {fastadmin-0.2.8.dist-info → fastadmin-0.2.10.dist-info}/WHEEL +0 -0
fastadmin/api/service.py
CHANGED
@@ -53,7 +53,7 @@ def convert_id(id: str | int | UUID) -> int | UUID | None:
|
|
53
53
|
if re.fullmatch(r"[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}", id):
|
54
54
|
return UUID(id)
|
55
55
|
|
56
|
-
logger.
|
56
|
+
logger.warning("Invalid id: %s", id)
|
57
57
|
return None
|
58
58
|
|
59
59
|
|
@@ -101,6 +101,7 @@ class ApiService:
|
|
101
101
|
) -> str:
|
102
102
|
model = settings.ADMIN_USER_MODEL
|
103
103
|
admin_model = get_admin_model(model)
|
104
|
+
|
104
105
|
if not admin_model:
|
105
106
|
raise AdminApiException(401, detail=f"{model} model is not registered.")
|
106
107
|
|
fastadmin/models/orms/django.py
CHANGED
fastadmin/models/orms/ponyorm.py
CHANGED
@@ -3,7 +3,7 @@ from typing import Any
|
|
3
3
|
from uuid import UUID
|
4
4
|
|
5
5
|
from asgiref.sync import sync_to_async
|
6
|
-
from pony.orm import commit, db_session, desc, flush
|
6
|
+
from pony.orm import commit, db_session, desc, flush
|
7
7
|
|
8
8
|
from fastadmin.models.base import InlineModelAdmin, ModelAdmin
|
9
9
|
from fastadmin.models.schemas import ModelFieldWidgetSchema, WidgetType
|
@@ -233,7 +233,7 @@ class PonyORMMixin:
|
|
233
233
|
:return: A tuple of list of objects and total count.
|
234
234
|
"""
|
235
235
|
|
236
|
-
qs = select(m
|
236
|
+
qs = getattr(self.model_cls, "select")(lambda m: m) # noqa: B009
|
237
237
|
if filters:
|
238
238
|
for field_with_condition, value in filters.items():
|
239
239
|
field = field_with_condition[0]
|
@@ -256,14 +256,17 @@ class PonyORMMixin:
|
|
256
256
|
case "contains":
|
257
257
|
pony_condition = "in"
|
258
258
|
case "icontains":
|
259
|
+
# TODO: support icontains here
|
259
260
|
pony_condition = "in"
|
260
261
|
filter_expr = f""""{value}" {pony_condition} m.{field}"""
|
261
262
|
qs = qs.filter(filter_expr)
|
262
263
|
|
263
264
|
if search and self.search_fields:
|
264
265
|
ids = []
|
265
|
-
for
|
266
|
-
|
266
|
+
for search_field in self.search_fields:
|
267
|
+
# TODO: support icontains here
|
268
|
+
filter_expr = f""""{search}" in m.{search_field}"""
|
269
|
+
qs_ids = qs.filter(filter_expr)
|
267
270
|
ids += [o.id for o in qs_ids]
|
268
271
|
qs = qs.filter(lambda m: m.id in set(ids))
|
269
272
|
|
@@ -362,11 +365,12 @@ class PonyORMMixin:
|
|
362
365
|
obj = next((i for i in self.model_cls.select(**{key_id: getattr(obj, key_id)})), None)
|
363
366
|
if not obj:
|
364
367
|
return
|
365
|
-
rel_model_cls = getattr(self.model_cls, field).py_type
|
366
|
-
rel_key_id = self.get_model_pk_name(rel_model_cls)
|
367
|
-
rel_objs = list(rel_model_cls.select(lambda o: getattr(o, rel_key_id) in ids))
|
368
368
|
obj.participants.clear()
|
369
|
-
|
369
|
+
if ids:
|
370
|
+
rel_model_cls = getattr(self.model_cls, field).py_type
|
371
|
+
rel_key_id = self.get_model_pk_name(rel_model_cls)
|
372
|
+
rel_objs = list(rel_model_cls.select(lambda o: getattr(o, rel_key_id) in ids))
|
373
|
+
obj.participants.add(rel_objs)
|
370
374
|
flush()
|
371
375
|
commit()
|
372
376
|
|
@@ -400,7 +400,8 @@ class SqlAlchemyMixin:
|
|
400
400
|
obj_field_name: obj_id,
|
401
401
|
}
|
402
402
|
)
|
403
|
-
|
403
|
+
if values:
|
404
|
+
await session.execute(orm_model_field.secondary.insert().values(values))
|
404
405
|
await session.commit()
|
405
406
|
|
406
407
|
async def orm_save_upload_field(self, obj: Any, field: str, base64: str) -> None:
|
@@ -1,6 +1,10 @@
|
|
1
|
+
import functools
|
2
|
+
import operator
|
1
3
|
from typing import Any
|
2
4
|
from uuid import UUID
|
3
5
|
|
6
|
+
from tortoise.expressions import Q
|
7
|
+
|
4
8
|
from fastadmin.models.base import InlineModelAdmin, ModelAdmin
|
5
9
|
from fastadmin.models.schemas import ModelFieldWidgetSchema, WidgetType
|
6
10
|
from fastadmin.settings import settings
|
@@ -244,11 +248,13 @@ class TortoiseMixin:
|
|
244
248
|
qs = qs.filter(**{f"{field}__{condition}" if condition != "exact" else field: value})
|
245
249
|
|
246
250
|
if search and self.search_fields:
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
251
|
+
qs = qs.filter(
|
252
|
+
functools.reduce(
|
253
|
+
operator.or_,
|
254
|
+
(Q(**{f + "__icontains": search}) for f in self.search_fields),
|
255
|
+
Q(),
|
256
|
+
)
|
257
|
+
)
|
252
258
|
|
253
259
|
if sort_by:
|
254
260
|
qs = qs.order_by(sort_by)
|
@@ -323,8 +329,6 @@ class TortoiseMixin:
|
|
323
329
|
|
324
330
|
:return: A list of ids.
|
325
331
|
"""
|
326
|
-
if not ids:
|
327
|
-
return
|
328
332
|
m2m_rel = getattr(obj, field)
|
329
333
|
|
330
334
|
await m2m_rel.clear()
|
@@ -335,7 +339,8 @@ class TortoiseMixin:
|
|
335
339
|
setattr(remote_model_obj, self.get_model_pk_name(remote_model), rel_id)
|
336
340
|
remote_model_obj._saved_in_db = True
|
337
341
|
remote_model_objs.append(remote_model_obj)
|
338
|
-
|
342
|
+
if remote_model_objs:
|
343
|
+
await m2m_rel.add(*remote_model_objs)
|
339
344
|
|
340
345
|
async def orm_save_upload_field(self, obj: Any, field: str, base64: str) -> None:
|
341
346
|
"""This method is used to save upload field.
|