fastadmin 0.3.8__tar.gz → 0.3.9__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.
Files changed (49) hide show
  1. {fastadmin-0.3.8 → fastadmin-0.3.9}/PKG-INFO +1 -1
  2. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/__init__.py +4 -0
  3. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/api/frameworks/django/app/api.py +15 -5
  4. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/api/frameworks/fastapi/api.py +17 -4
  5. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/api/frameworks/flask/api.py +16 -5
  6. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/api/schemas.py +16 -0
  7. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/api/service.py +3 -2
  8. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/models/base.py +10 -2
  9. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/models/decorators.py +1 -1
  10. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/static/index.min.js +173 -173
  11. {fastadmin-0.3.8 → fastadmin-0.3.9}/pyproject.toml +1 -1
  12. {fastadmin-0.3.8 → fastadmin-0.3.9}/LICENSE +0 -0
  13. {fastadmin-0.3.8 → fastadmin-0.3.9}/README.md +0 -0
  14. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/api/__init__.py +0 -0
  15. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/api/exceptions.py +0 -0
  16. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/api/frameworks/__init__.py +0 -0
  17. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/api/frameworks/django/__init__.py +0 -0
  18. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/api/frameworks/django/app/__init__.py +0 -0
  19. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/api/frameworks/django/app/urls.py +0 -0
  20. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/api/frameworks/django/app/views.py +0 -0
  21. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/api/frameworks/fastapi/__init__.py +0 -0
  22. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/api/frameworks/fastapi/app.py +0 -0
  23. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/api/frameworks/fastapi/views.py +0 -0
  24. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/api/frameworks/flask/__init__.py +0 -0
  25. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/api/frameworks/flask/app.py +0 -0
  26. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/api/frameworks/flask/views.py +0 -0
  27. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/api/helpers.py +0 -0
  28. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/models/__init__.py +0 -0
  29. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/models/helpers.py +0 -0
  30. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/models/orms/__init__.py +0 -0
  31. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/models/orms/django.py +0 -0
  32. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/models/orms/ponyorm.py +0 -0
  33. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/models/orms/sqlalchemy.py +0 -0
  34. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/models/orms/tortoise.py +0 -0
  35. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/models/schemas.py +0 -0
  36. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/settings.py +0 -0
  37. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/static/assets/worker-6Z7niv9l.js +0 -0
  38. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/static/assets/worker-C151k0-L.js +0 -0
  39. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/static/assets/worker-C9KPOOKD.js +0 -0
  40. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/static/assets/worker-D1fCgYB7.js +0 -0
  41. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/static/assets/worker-D3TWcJOI.js +0 -0
  42. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/static/assets/worker-DRNcaZ-V.js +0 -0
  43. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/static/assets/worker-MF2p-l5_.js +0 -0
  44. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/static/images/favicon.png +0 -0
  45. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/static/images/header-logo.svg +0 -0
  46. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/static/images/sign-in-logo.svg +0 -0
  47. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/static/index.html +0 -0
  48. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/static/index.min.css +0 -0
  49. {fastadmin-0.3.8 → fastadmin-0.3.9}/fastadmin/templates/index.html +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastadmin
3
- Version: 0.3.8
3
+ Version: 0.3.9
4
4
  Summary: FastAdmin is an easy-to-use Admin Dashboard App for FastAPI/Flask/Django inspired by Django Admin.
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -32,6 +32,10 @@ try:
32
32
  except ModuleNotFoundError: # pragma: no cover
33
33
  logging.info("TortoiseORM is not installed") # pragma: no cover
34
34
 
35
+ # api
36
+ from fastadmin.api.exceptions import AdminApiException # noqa: F401
37
+ from fastadmin.api.schemas import ActionResponseSchema, ActionResponseType # noqa: F401
38
+
35
39
  # models
36
40
  from fastadmin.models.base import DashboardWidgetAdmin, InlineModelAdmin, ModelAdmin # noqa: F401
37
41
  from fastadmin.models.decorators import action, display, register, register_widget # noqa: F401
@@ -13,7 +13,13 @@ from django.http.request import HttpRequest
13
13
 
14
14
  from fastadmin.api.exceptions import AdminApiException
15
15
  from fastadmin.api.helpers import is_valid_id, parse_list_filters_from_query_params
16
- from fastadmin.api.schemas import ActionInputSchema, ExportInputSchema, SignInInputSchema
16
+ from fastadmin.api.schemas import (
17
+ ActionInputSchema,
18
+ ActionResponseSchema,
19
+ ActionResponseType,
20
+ ExportInputSchema,
21
+ SignInInputSchema,
22
+ )
17
23
  from fastadmin.api.service import ApiService, get_user_id_from_session_id
18
24
  from fastadmin.settings import settings
19
25
 
@@ -379,21 +385,25 @@ async def action(
379
385
  :params model: a name of model.
380
386
  :params action: a name of action.
381
387
  :params payload: a payload object.
382
- :return: A list of objects.
388
+ :return: action result.
383
389
  """
384
390
  if request.method != "POST":
385
391
  return JsonResponse({"error": "Method not allowed"}, status=405)
386
392
  try:
387
393
  payload = ActionInputSchema(**json.loads(request.body))
388
- await api_service.action(
394
+ response = await api_service.action(
389
395
  request.COOKIES.get(settings.ADMIN_SESSION_ID_KEY, None),
390
396
  model,
391
397
  action,
392
398
  payload,
393
399
  request=request,
394
400
  )
395
- return JsonResponse({})
396
-
401
+ if not response:
402
+ response = ActionResponseSchema(
403
+ type=ActionResponseType.MESSAGE,
404
+ data="Successfully applied",
405
+ )
406
+ return JsonResponse(asdict(response))
397
407
  except AdminApiException as e:
398
408
  return JsonResponse({"detail": e.detail}, status=e.status_code)
399
409
 
@@ -1,4 +1,5 @@
1
1
  import logging
2
+ from dataclasses import asdict
2
3
  from typing import Any
3
4
  from uuid import UUID
4
5
 
@@ -7,7 +8,13 @@ from fastapi.responses import Response, StreamingResponse
7
8
 
8
9
  from fastadmin.api.exceptions import AdminApiException
9
10
  from fastadmin.api.helpers import parse_list_filters_from_query_params
10
- from fastadmin.api.schemas import ActionInputSchema, ExportInputSchema, SignInInputSchema
11
+ from fastadmin.api.schemas import (
12
+ ActionInputSchema,
13
+ ActionResponseSchema,
14
+ ActionResponseType,
15
+ ExportInputSchema,
16
+ SignInInputSchema,
17
+ )
11
18
  from fastadmin.api.service import ApiService, get_user_id_from_session_id
12
19
  from fastadmin.models.schemas import ConfigurationSchema
13
20
  from fastadmin.settings import settings
@@ -328,22 +335,28 @@ async def action(
328
335
  model: str,
329
336
  action: str,
330
337
  payload: ActionInputSchema,
331
- ) -> None:
338
+ ) -> dict:
332
339
  """This method is used to perform an action.
333
340
 
334
341
  :params model: a name of model.
335
342
  :params action: a name of action.
336
343
  :params payload: a payload object.
337
- :return: A list of objects.
344
+ :return: action result.
338
345
  """
339
346
  try:
340
- return await api_service.action(
347
+ response = await api_service.action(
341
348
  request.cookies.get(settings.ADMIN_SESSION_ID_KEY, None),
342
349
  model,
343
350
  action,
344
351
  payload,
345
352
  request=request,
346
353
  )
354
+ if not response:
355
+ response = ActionResponseSchema(
356
+ type=ActionResponseType.MESSAGE,
357
+ data="Successfully applied",
358
+ )
359
+ return asdict(response)
347
360
  except AdminApiException as e:
348
361
  raise HTTPException(e.status_code, detail=e.detail) from None
349
362
 
@@ -7,7 +7,13 @@ from werkzeug.exceptions import HTTPException
7
7
 
8
8
  from fastadmin.api.exceptions import AdminApiException
9
9
  from fastadmin.api.helpers import is_valid_id, parse_list_filters_from_query_params
10
- from fastadmin.api.schemas import ActionInputSchema, ExportInputSchema, SignInInputSchema
10
+ from fastadmin.api.schemas import (
11
+ ActionInputSchema,
12
+ ActionResponseSchema,
13
+ ActionResponseType,
14
+ ExportInputSchema,
15
+ SignInInputSchema,
16
+ )
11
17
  from fastadmin.api.service import ApiService, get_user_id_from_session_id
12
18
  from fastadmin.settings import settings
13
19
 
@@ -336,25 +342,30 @@ async def delete(
336
342
  async def action(
337
343
  model: str,
338
344
  action: str,
339
- ) -> dict:
345
+ ) -> Response:
340
346
  """This method is used to perform an action.
341
347
 
342
348
  :params model: a name of model.
343
349
  :params action: a name of action.
344
350
  :params payload: a payload object.
345
- :return: A list of objects.
351
+ :return: action result.
346
352
  """
347
353
  try:
348
354
  request_payload: dict = request.json
349
355
  payload: ActionInputSchema = ActionInputSchema(**request_payload)
350
- await api_service.action(
356
+ response = await api_service.action(
351
357
  request.cookies.get(settings.ADMIN_SESSION_ID_KEY, None),
352
358
  model,
353
359
  action,
354
360
  payload,
355
361
  request=request,
356
362
  )
357
- return {}
363
+ if not response:
364
+ response = ActionResponseSchema(
365
+ type=ActionResponseType.MESSAGE,
366
+ data="Successfully applied",
367
+ )
368
+ return make_response(asdict(response))
358
369
  except AdminApiException as e:
359
370
  http_exception = HTTPException(e.detail)
360
371
  http_exception.code = e.status_code
@@ -10,6 +10,13 @@ class ExportFormat(str, Enum):
10
10
  JSON = "JSON"
11
11
 
12
12
 
13
+ class ActionResponseType(str, Enum):
14
+ """Action response type"""
15
+
16
+ DOWNLOAD_BASE64 = "DOWNLOAD_BASE64"
17
+ MESSAGE = "MESSAGE"
18
+
19
+
13
20
  @dataclass
14
21
  class DashboardWidgetQuerySchema:
15
22
  """DashboardWidge query schema"""
@@ -70,3 +77,12 @@ class ActionInputSchema:
70
77
  """Action input schema"""
71
78
 
72
79
  ids: list[int | UUID]
80
+
81
+
82
+ @dataclass
83
+ class ActionResponseSchema:
84
+ """Action response schema"""
85
+
86
+ type: ActionResponseType
87
+ data: str
88
+ file_name: str | None = None
@@ -14,6 +14,7 @@ from fastadmin.api.exceptions import AdminApiException
14
14
  from fastadmin.api.helpers import sanitize_filter_key, sanitize_filter_value
15
15
  from fastadmin.api.schemas import (
16
16
  ActionInputSchema,
17
+ ActionResponseSchema,
17
18
  ChangePasswordInputSchema,
18
19
  DashboardWidgetDataOutputSchema,
19
20
  DashboardWidgetQuerySchema,
@@ -478,7 +479,7 @@ class ApiService:
478
479
  action: str,
479
480
  payload: ActionInputSchema,
480
481
  request: Any | None = None,
481
- ) -> None:
482
+ ) -> ActionResponseSchema | None:
482
483
  _current_user_id, current_user = await self._get_authenticated_user(session_id)
483
484
 
484
485
  admin_model = get_admin_or_admin_inline_model(model)
@@ -498,7 +499,7 @@ class ApiService:
498
499
  else:
499
500
  action_function_fn = sync_to_async(action_function)
500
501
 
501
- await action_function_fn(payload.ids)
502
+ return await action_function_fn(payload.ids)
502
503
 
503
504
  async def get_configuration(
504
505
  self,
@@ -4,6 +4,7 @@ import inspect
4
4
  import json
5
5
  from collections.abc import Sequence
6
6
  from contextvars import ContextVar
7
+ from decimal import Decimal
7
8
  from io import BytesIO, StringIO
8
9
  from typing import Any
9
10
  from uuid import UUID
@@ -31,7 +32,7 @@ class BaseModelAdmin:
31
32
  # @action(
32
33
  # description="Mark selected stories as published",
33
34
  # )
34
- # async def make_published(self, objs: list[Any]) -> None:
35
+ # async def make_published(self, objs: list[Any]) -> ActionResponseSchema | None:
35
36
  # ...
36
37
  actions: Sequence[str] = ()
37
38
 
@@ -384,7 +385,14 @@ class BaseModelAdmin:
384
385
  :params attributes_to_serizalize: a list of attributes to serialize.
385
386
  :return: A dict of serialized attributes.
386
387
  """
387
- serialized_dict = {field.name: getattr(obj, field.column_name) for field in attributes_to_serizalize}
388
+ serialized_dict: dict[str, Any] = {}
389
+ for field in attributes_to_serizalize:
390
+ value = getattr(obj, field.column_name)
391
+ if isinstance(value, Decimal):
392
+ # Avoid scientific notation for Decimal values in API responses,
393
+ # e.g. 3.75E+3 -> "3750"
394
+ value = format(value, "f")
395
+ serialized_dict[field.name] = value
388
396
  if inspect.iscoroutinefunction(obj.__str__):
389
397
  str_fn = obj.__str__
390
398
  else:
@@ -5,7 +5,7 @@ def action(function=None, *, description: str | None = None):
5
5
  @action(
6
6
  description="Mark selected stories as published",
7
7
  )
8
- async def make_published(self, objs: list[Any]) -> None:
8
+ async def make_published(self, objs: list[Any]) -> ActionResponseSchema | None:
9
9
  ...
10
10
 
11
11
  :param function: A function to decorate.