fastadmin 0.7.0__tar.gz → 0.8.0__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.7.0 → fastadmin-0.8.0}/PKG-INFO +1 -1
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/__init__.py +1 -0
- fastadmin-0.8.0/fastadmin/api/encoders.py +70 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/models/base.py +7 -1
- {fastadmin-0.7.0 → fastadmin-0.8.0}/pyproject.toml +1 -1
- {fastadmin-0.7.0 → fastadmin-0.8.0}/LICENSE.md +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/README.md +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/api/__init__.py +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/api/exceptions.py +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/api/frameworks/__init__.py +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/api/frameworks/django/__init__.py +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/api/frameworks/django/app/__init__.py +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/api/frameworks/django/app/api.py +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/api/frameworks/django/app/urls.py +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/api/frameworks/django/app/views.py +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/api/frameworks/fastapi/__init__.py +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/api/frameworks/fastapi/api.py +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/api/frameworks/fastapi/app.py +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/api/frameworks/fastapi/views.py +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/api/frameworks/flask/__init__.py +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/api/frameworks/flask/api.py +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/api/frameworks/flask/app.py +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/api/frameworks/flask/views.py +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/api/helpers.py +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/api/schemas.py +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/api/service.py +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/models/__init__.py +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/models/decorators.py +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/models/helpers.py +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/models/orms/__init__.py +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/models/orms/django.py +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/models/orms/ponyorm.py +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/models/orms/sqlalchemy.py +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/models/orms/tortoise.py +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/models/orms/yaraorm.py +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/models/schemas.py +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/settings.py +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/static/assets/worker-6Z7niv9l.js +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/static/assets/worker-C151k0-L.js +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/static/assets/worker-C9KPOOKD.js +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/static/assets/worker-D1fCgYB7.js +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/static/assets/worker-D3TWcJOI.js +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/static/assets/worker-DRNcaZ-V.js +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/static/assets/worker-MF2p-l5_.js +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/static/images/favicon.png +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/static/images/header-logo.svg +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/static/images/sign-in-logo.svg +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/static/index.html +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/static/index.min.css +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/static/index.min.js +0 -0
- {fastadmin-0.7.0 → fastadmin-0.8.0}/fastadmin/templates/index.html +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fastadmin
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.0
|
|
4
4
|
Summary: FastAdmin is an easy-to-use Admin Dashboard App for FastAPI/Flask/Django inspired by Django Admin.
|
|
5
5
|
Keywords: admin,dashboard,fastapi,flask,django,tortoise-orm,sqlalchemy,pony,yara-orm,admin-dashboard,django-admin
|
|
6
6
|
Author: Seva D
|
|
@@ -38,6 +38,7 @@ except ModuleNotFoundError: # pragma: no cover
|
|
|
38
38
|
logging.info("Yara ORM is not installed") # pragma: no cover
|
|
39
39
|
|
|
40
40
|
# api
|
|
41
|
+
from fastadmin.api.encoders import register_encoder, unregister_encoder # noqa: F401
|
|
41
42
|
from fastadmin.api.exceptions import AdminApiException # noqa: F401
|
|
42
43
|
|
|
43
44
|
# models
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""User-registerable custom encoders for admin API serialization.
|
|
2
|
+
|
|
3
|
+
Model field values are converted to JSON-serializable representations during
|
|
4
|
+
serialization (see :meth:`fastadmin.models.base.BaseModelAdmin.serialize_obj_attributes`).
|
|
5
|
+
Register a custom encoder to control how instances of a given type are represented
|
|
6
|
+
in every admin API response — e.g. a custom datetime format, an ``Enum``'s label,
|
|
7
|
+
or a domain value object.
|
|
8
|
+
|
|
9
|
+
Example:
|
|
10
|
+
|
|
11
|
+
.. code-block:: python
|
|
12
|
+
|
|
13
|
+
import datetime
|
|
14
|
+
|
|
15
|
+
from fastadmin import register_encoder
|
|
16
|
+
|
|
17
|
+
# Render every datetime as "2024-01-31 14:05" instead of ISO 8601.
|
|
18
|
+
register_encoder(datetime.datetime, lambda dt: dt.strftime("%Y-%m-%d %H:%M"))
|
|
19
|
+
|
|
20
|
+
Encoders are matched via ``isinstance`` in registration order, so register more
|
|
21
|
+
specific types before their base types.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from collections.abc import Callable
|
|
25
|
+
from typing import Any
|
|
26
|
+
|
|
27
|
+
# Maps a type to a function converting an instance of that type to a JSON-serializable value.
|
|
28
|
+
CUSTOM_ENCODERS: dict[type, Callable[[Any], Any]] = {}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def register_encoder(type_: type, encoder: Callable[[Any], Any]) -> None:
|
|
32
|
+
"""Register a custom encoder for a type used across all admin API responses.
|
|
33
|
+
|
|
34
|
+
:params type_: the type to encode (matched via ``isinstance``).
|
|
35
|
+
:params encoder: a callable converting an instance to a JSON-serializable value.
|
|
36
|
+
:return: None.
|
|
37
|
+
"""
|
|
38
|
+
CUSTOM_ENCODERS[type_] = encoder
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def unregister_encoder(type_: type) -> None:
|
|
42
|
+
"""Remove a previously registered encoder for a type (no-op if absent).
|
|
43
|
+
|
|
44
|
+
:params type_: the type whose encoder should be removed.
|
|
45
|
+
:return: None.
|
|
46
|
+
"""
|
|
47
|
+
CUSTOM_ENCODERS.pop(type_, None)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def clear_encoders() -> None:
|
|
51
|
+
"""Remove all registered custom encoders.
|
|
52
|
+
|
|
53
|
+
:return: None.
|
|
54
|
+
"""
|
|
55
|
+
CUSTOM_ENCODERS.clear()
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def apply_custom_encoders(value: Any) -> Any:
|
|
59
|
+
"""Return ``value`` encoded by the first matching custom encoder, else unchanged.
|
|
60
|
+
|
|
61
|
+
Types are matched via ``isinstance`` in registration order, so a more specific
|
|
62
|
+
type registered before its base type wins.
|
|
63
|
+
|
|
64
|
+
:params value: the value to encode.
|
|
65
|
+
:return: the encoded value, or the original value if no encoder matches.
|
|
66
|
+
"""
|
|
67
|
+
for type_, encoder in CUSTOM_ENCODERS.items():
|
|
68
|
+
if isinstance(value, type_):
|
|
69
|
+
return encoder(value)
|
|
70
|
+
return value
|
|
@@ -11,6 +11,7 @@ from uuid import UUID
|
|
|
11
11
|
|
|
12
12
|
from asgiref.sync import sync_to_async
|
|
13
13
|
|
|
14
|
+
from fastadmin.api.encoders import apply_custom_encoders
|
|
14
15
|
from fastadmin.api.schemas import ExportFormat
|
|
15
16
|
from fastadmin.models.schemas import ModelFieldWidgetSchema, WidgetType
|
|
16
17
|
|
|
@@ -419,7 +420,12 @@ class BaseModelAdmin:
|
|
|
419
420
|
serialized_dict: dict[str, Any] = {}
|
|
420
421
|
for field in attributes_to_serizalize:
|
|
421
422
|
value = getattr(obj, field.column_name)
|
|
422
|
-
|
|
423
|
+
# Let user-registered encoders (e.g. a custom datetime format) take
|
|
424
|
+
# precedence over the built-in handling below.
|
|
425
|
+
encoded = apply_custom_encoders(value)
|
|
426
|
+
if encoded is not value:
|
|
427
|
+
value = encoded
|
|
428
|
+
elif isinstance(value, Decimal):
|
|
423
429
|
# Avoid scientific notation for Decimal values in API responses,
|
|
424
430
|
# e.g. 3.75E+3 -> "3750"
|
|
425
431
|
value = format(value, "f")
|
|
@@ -4,7 +4,7 @@ build-backend = "uv_build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "fastadmin"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.8.0"
|
|
8
8
|
description = "FastAdmin is an easy-to-use Admin Dashboard App for FastAPI/Flask/Django inspired by Django Admin."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.12"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|