fastgenerateapi 1.1.20__tar.gz → 1.1.24__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.

Potentially problematic release.


This version of fastgenerateapi might be problematic. Click here for more details.

Files changed (115) hide show
  1. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/PKG-INFO +1 -1
  2. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/__version__.py +1 -1
  3. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/api_view/base_view.py +29 -2
  4. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/api_view/create_view.py +15 -7
  5. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/api_view/delete_filter_view.py +15 -5
  6. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/api_view/delete_tree_view.py +13 -5
  7. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/api_view/delete_view.py +13 -5
  8. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/api_view/get_all_view.py +21 -16
  9. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/api_view/get_one_view.py +9 -15
  10. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/api_view/get_relation_view.py +8 -3
  11. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/api_view/get_tree_view.py +8 -3
  12. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/api_view/switch_view.py +2 -5
  13. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/api_view/update_relation_view.py +9 -2
  14. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/api_view/update_view.py +12 -5
  15. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/schemas_factory/get_all_schema_factory.py +32 -28
  16. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/settings/__init__.py +1 -0
  17. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/settings/all_settings.py +34 -24
  18. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/settings/db_settings.py +1 -1
  19. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/settings/etcd_settings.py +7 -0
  20. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi.egg-info/PKG-INFO +1 -1
  21. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/LICENSE +0 -0
  22. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/README.md +0 -0
  23. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/__init__.py +0 -0
  24. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/api_view/__init__.py +0 -0
  25. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/api_view/api_view.py +0 -0
  26. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/api_view/mixin/__init__.py +0 -0
  27. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/api_view/mixin/base_mixin.py +0 -0
  28. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/api_view/mixin/dbmodel_mixin.py +0 -0
  29. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/api_view/mixin/get_mixin.py +0 -0
  30. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/api_view/mixin/response_mixin.py +0 -0
  31. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/api_view/mixin/save_mixin.py +0 -0
  32. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/api_view/mixin/tool_mixin.py +0 -0
  33. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/api_view/mixin/utils/__init__.py +0 -0
  34. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/api_view/mixin/utils/docx_util.py +0 -0
  35. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/api_view/mixin/utils/file_util.py +0 -0
  36. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/api_view/mixin/utils/pdf_util.py +0 -0
  37. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/api_view/mixin/utils/xlsx_util.py +0 -0
  38. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/api_view/mixin/utils/zip_util.py +0 -0
  39. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/api_view/sql_get_view.py +0 -0
  40. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/cache/__init__.py +0 -0
  41. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/cache/cache_decorator.py +0 -0
  42. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/cache/key_builder.py +0 -0
  43. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/channel/__init__.py +0 -0
  44. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/channel/connection_manager.py +0 -0
  45. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/channel/consumer.py +0 -0
  46. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/channel/websocket_view.py +0 -0
  47. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/controller/__init__.py +0 -0
  48. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/controller/filter_controller.py +0 -0
  49. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/controller/router_controller.py +0 -0
  50. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/controller/rpc_controller.py +0 -0
  51. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/controller/search_controller.py +0 -0
  52. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/controller/ws_controller.py +0 -0
  53. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/data_type/__init__.py +0 -0
  54. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/data_type/data_type.py +0 -0
  55. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/data_type/mysql_data_type.py +0 -0
  56. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/deps/__init__.py +0 -0
  57. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/deps/filter_params_deps.py +0 -0
  58. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/deps/paginator_deps.py +0 -0
  59. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/deps/tree_params_deps.py +0 -0
  60. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/example/__init__.py +0 -0
  61. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/example/models.py +0 -0
  62. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/example/routers.py +0 -0
  63. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/example/schemas.py +0 -0
  64. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/example/views.py +0 -0
  65. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/fastapi_utils/__init__.py +0 -0
  66. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/fastapi_utils/all.py +0 -0
  67. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/fastapi_utils/param_utils.py +0 -0
  68. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/fastapi_utils/response_utils.py +0 -0
  69. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/model/__init__.py +0 -0
  70. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/model/base_model.py +0 -0
  71. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/my_fields/__init__.py +0 -0
  72. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/my_fields/aes_field.py +0 -0
  73. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/my_fields/enum_field.py +0 -0
  74. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/my_fields/pk_field.py +0 -0
  75. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/my_fields/pwd_field.py +0 -0
  76. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/my_fields/soft_delete_field.py +0 -0
  77. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/my_fields/validator.py +0 -0
  78. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/pydantic_utils/__init__.py +0 -0
  79. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/pydantic_utils/base_model.py +0 -0
  80. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/pydantic_utils/base_settings.py +0 -0
  81. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/pydantic_utils/json_encoders.py +0 -0
  82. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/schemas_factory/__init__.py +0 -0
  83. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/schemas_factory/common_function.py +0 -0
  84. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/schemas_factory/common_schema_factory.py +0 -0
  85. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/schemas_factory/create_schema_factory.py +0 -0
  86. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/schemas_factory/filter_schema_factory.py +0 -0
  87. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/schemas_factory/get_one_schema_factory.py +0 -0
  88. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/schemas_factory/get_relation_schema_factory.py +0 -0
  89. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/schemas_factory/get_tree_schema_factory.py +0 -0
  90. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/schemas_factory/response_factory.py +0 -0
  91. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/schemas_factory/sql_get_all_schema_factory.py +0 -0
  92. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/schemas_factory/update_schema_factory.py +0 -0
  93. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/settings/app_settings.py +0 -0
  94. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/settings/file_settings.py +0 -0
  95. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/settings/jwt_settings.py +0 -0
  96. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/settings/otlp_settings.py +0 -0
  97. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/settings/redis_settings.py +0 -0
  98. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/settings/sms_settings.py +0 -0
  99. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/settings/system_settings.py +0 -0
  100. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/utils/__init__.py +0 -0
  101. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/utils/aes.py +0 -0
  102. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/utils/auto_discover.py +0 -0
  103. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/utils/exception.py +0 -0
  104. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/utils/file_utils.py +0 -0
  105. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/utils/pwd_utils.py +0 -0
  106. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/utils/ramdom_utils.py +0 -0
  107. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/utils/snowflake.py +0 -0
  108. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/utils/str_util.py +0 -0
  109. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi/utils/swagger_to_js.py +0 -0
  110. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi.egg-info/SOURCES.txt +0 -0
  111. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi.egg-info/dependency_links.txt +0 -0
  112. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/fastgenerateapi.egg-info/top_level.txt +0 -0
  113. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/script/__init__.py +0 -0
  114. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/setup.cfg +0 -0
  115. {fastgenerateapi-1.1.20 → fastgenerateapi-1.1.24}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fastgenerateapi
3
- Version: 1.1.20
3
+ Version: 1.1.24
4
4
  Summary: FastAPIView Class View
5
5
  Author: ShiLiang
6
6
  Author-email: 2509144896@qq.com
@@ -8,7 +8,7 @@
8
8
  # d8888P
9
9
 
10
10
 
11
- VERSION = (1, 1, 20)
11
+ VERSION = (1, 1, 24)
12
12
 
13
13
  __version__ = '.'.join(map(str, VERSION))
14
14
 
@@ -15,6 +15,7 @@ from fastgenerateapi.api_view.mixin.base_mixin import BaseMixin
15
15
  from fastgenerateapi.api_view.mixin.dbmodel_mixin import DBModelMixin
16
16
  from fastgenerateapi.api_view.mixin.response_mixin import ResponseMixin
17
17
  from fastgenerateapi.api_view.mixin.tool_mixin import ToolMixin
18
+ from fastgenerateapi.schemas_factory import get_one_schema_factory, response_factory
18
19
  from fastgenerateapi.settings.all_settings import settings
19
20
  from fastgenerateapi.utils.exception import NOT_FOUND
20
21
 
@@ -24,7 +25,7 @@ class BaseView(BaseMixin, ResponseMixin, ToolMixin, DBModelMixin):
24
25
  prefix: Optional[str] = None # 路由追加后缀
25
26
  model_class: Optional[Type[Model]] = None # 数据库模型
26
27
  prefetch_related_fields: Union[None, dict] = None
27
- schema: Optional[Type[BaseModel]] = None # 返回序列化
28
+ schema: Optional[Type[BaseModel]] = None # 返回序列化[未使用]
28
29
  dependencies: Optional[Sequence[params.Depends]] = None
29
30
  tags: Optional[List[str]] = None # swagger标签
30
31
  router_args: Dict[str, any] = None
@@ -161,7 +162,7 @@ class BaseView(BaseMixin, ResponseMixin, ToolMixin, DBModelMixin):
161
162
  model_class: Type[Model], # 数据库模型
162
163
  model: Union[Model, None] = None
163
164
  ):
164
- check_unique_fields = cls._get_unique_fields(model_class) + cls._get_foreign_key_fields(model_class)
165
+ check_unique_fields = cls._get_unique_fields(model_class)
165
166
  check_unique_together_fields = cls._get_unique_together_fields(model_class)
166
167
  for unique_field in check_unique_fields:
167
168
  if hasattr(request_data, unique_field):
@@ -225,5 +226,31 @@ class BaseView(BaseMixin, ResponseMixin, ToolMixin, DBModelMixin):
225
226
  result[key] = val[0]
226
227
  return result
227
228
 
229
+ def gen_get_one_response_schema(self):
230
+ if not hasattr(self, "get_one_schema"):
231
+ get_one_schema_include = []
232
+ if hasattr(self, "is_with_prefetch") and self.is_with_prefetch and self.prefetch_related_fields:
233
+ for key, value in self.prefetch_related_fields.items():
234
+ if value and type(value) in [list, tuple, set]:
235
+ for val in value:
236
+ val_str = val
237
+ if type(val) in [list, tuple, set]:
238
+ val_str = val[0]
239
+ get_one_schema_include.append(key + "__" + val_str)
240
+ self.get_one_schema = get_one_schema_factory(model_class=self.model_class, include=get_one_schema_include)
241
+
242
+ return self.get_one_schema
243
+
244
+ def gen_get_one_response_schema_factory(self):
245
+ """
246
+ 如果get_one_response_schema不存在,则生成
247
+ :return:
248
+ """
249
+ self.gen_get_one_response_schema()
250
+ if not hasattr(self, "get_one_response_schema"):
251
+ self.get_one_response_schema_factory = response_factory(self.get_one_schema, name="GetOne")
252
+
253
+ return self.get_one_response_schema_factory
254
+
228
255
 
229
256
 
@@ -1,3 +1,4 @@
1
+ import inspect
1
2
  from typing import Optional, Type, Union, Any
2
3
 
3
4
  from fastapi import Depends
@@ -18,16 +19,18 @@ from fastgenerateapi.settings.all_settings import settings
18
19
 
19
20
  class CreateView(BaseView, SaveMixin):
20
21
 
21
- create_schema: Optional[Type[BaseModel]] = None
22
22
  create_route: Union[bool, DEPENDENCIES] = True
23
+ create_schema: Optional[Type[BaseModel]] = None
24
+ create_response_schema: Optional[Type[BaseModel]] = None
23
25
  """
26
+ create_route: 创建路由开关,可以放依赖函数列表
24
27
  create_schema: 创建请求模型;
25
28
  优先级:
26
29
  - create_schema:参数传入
27
30
  - create_schema_factory:数据库模型自动生成
28
31
  - 优选模型层[include, exclude, create_include, create_exclude](同时存在交集)
29
32
  - 无include和exclude默认模型层所有字段
30
- create_route: 创建路由开关,可以放依赖函数列表
33
+ create_response_schema: 创建返回模型
31
34
  """
32
35
 
33
36
  @atomic()
@@ -91,10 +94,15 @@ class CreateView(BaseView, SaveMixin):
91
94
  if not self.create_route:
92
95
  return
93
96
  self.create_schema = self.create_schema or create_schema_factory(self.model_class)
94
- if not hasattr(self, "get_one_schema"):
95
- self.get_one_schema = get_one_schema_factory(model_class=self.model_class)
96
- if not hasattr(self, "get_one_response_schema"):
97
- self.get_one_response_schema = response_factory(self.get_one_schema, name="GetOne")
97
+
98
+ func_type = inspect.signature(self.create).return_annotation
99
+ if func_type != inspect._empty and func_type is not None:
100
+ self.create_response_schema = func_type
101
+ if self.create_response_schema:
102
+ self.create_response_schema_factory = response_factory(self.create_response_schema, name="Create")
103
+ else:
104
+ self.create_response_schema_factory = self.gen_get_one_response_schema_factory()
105
+
98
106
  doc = self.create.__doc__
99
107
  summary = doc.strip().split("\n")[0] if doc else f"Create"
100
108
  path = f"/{settings.app_settings.ROUTER_CREATE_SUFFIX_FIELD}" if settings.app_settings.ROUTER_WHETHER_ADD_SUFFIX else ""
@@ -102,7 +110,7 @@ class CreateView(BaseView, SaveMixin):
102
110
  path=path,
103
111
  endpoint=self._create_decorator(),
104
112
  methods=["POST"],
105
- response_model=self.get_one_response_schema, # type: ignore
113
+ response_model=self.create_response_schema_factory, # type: ignore
106
114
  summary=summary,
107
115
  dependencies=self.create_route,
108
116
  )
@@ -1,8 +1,10 @@
1
+ import inspect
1
2
  from typing import Optional, Type, Any, Union
2
3
 
3
4
  from fastapi import Query, Depends
4
5
  from fastapi.security import OAuth2PasswordBearer
5
6
  from fastapi.types import DecoratedCallable
7
+ from pydantic import BaseModel
6
8
  from starlette.requests import Request
7
9
  from starlette.responses import JSONResponse
8
10
  from tortoise.transactions import atomic
@@ -17,9 +19,12 @@ from fastgenerateapi.settings.all_settings import settings
17
19
  class DeleteFilterView(BaseView):
18
20
 
19
21
  delete_filter_route: Union[bool, DEPENDENCIES] = True
22
+ delete_filter_response_schema: Optional[Type[BaseModel]] = None
20
23
  """
21
24
  必须继承 GetAllView 才能使用
22
25
  与 GetAllView 同步的筛选条件
26
+ delete_filter_route: 删除路由开关,可以放依赖函数列表
27
+ delete_filter_response_schema: 删除返回模型
23
28
  """
24
29
 
25
30
  @atomic()
@@ -50,10 +55,15 @@ class DeleteFilterView(BaseView):
50
55
  def _handler_destroy_filter_settings(self):
51
56
  if self.delete_filter_route:
52
57
  return
53
- if not hasattr(self, "get_one_schema"):
54
- self.get_one_schema = get_one_schema_factory(model_class=self.model_class)
55
- if not hasattr(self, "get_one_response_schema"):
56
- self.get_one_response_schema = response_factory(self.get_one_schema, name="GetOne")
58
+
59
+ func_type = inspect.signature(self.destroy_filter).return_annotation
60
+ if func_type != inspect._empty and func_type is not None:
61
+ self.delete_filter_response_schema = func_type
62
+ if self.delete_filter_response_schema:
63
+ self.delete_filter_response_schema_factory = response_factory(self.delete_filter_response_schema, name="DeleteFilter")
64
+ else:
65
+ self.delete_filter_response_schema_factory = self.gen_get_one_response_schema_factory()
66
+
57
67
  doc = self.destroy_filter.__doc__
58
68
  summary = doc.strip().split("\n")[0] if doc else "Delete Filter"
59
69
  path = f"/{settings.app_settings.ROUTER_FILTER_DELETE_SUFFIX_FIELD}" if settings.app_settings.ROUTER_WHETHER_ADD_SUFFIX else ""
@@ -61,7 +71,7 @@ class DeleteFilterView(BaseView):
61
71
  path=path,
62
72
  endpoint=self._delete_filter_decorator(),
63
73
  methods=["DELETE"],
64
- response_model=Optional[self.get_one_response_schema],
74
+ response_model=Optional[self.delete_filter_response_schema_factory],
65
75
  summary=summary,
66
76
  dependencies=self.delete_filter_route,
67
77
  )
@@ -1,3 +1,4 @@
1
+ import inspect
1
2
  import time
2
3
  from typing import Optional, Type, Any, Union
3
4
 
@@ -20,9 +21,11 @@ class DeleteTreeView(BaseView):
20
21
 
21
22
  delete_tree_route: Union[bool, DEPENDENCIES] = True
22
23
  delete_tree_schema: Optional[Type[BaseModel]] = IdList
24
+ delete_tree_response_schema: Optional[Type[BaseModel]] = None
23
25
  """
24
26
  delete_route: 删除路由开关,可以放依赖函数列表
25
27
  delete_schema: 删除请求模型
28
+ delete_tree_response_schema: 删除返回模型
26
29
  """
27
30
 
28
31
  @atomic()
@@ -77,10 +80,15 @@ class DeleteTreeView(BaseView):
77
80
  def _handler_delete_tree_settings(self):
78
81
  if self.delete_tree_route:
79
82
  return
80
- if not hasattr(self, "get_one_schema"):
81
- self.get_one_schema = get_one_schema_factory(model_class=self.model_class)
82
- if not hasattr(self, "get_one_response_schema"):
83
- self.get_one_response_schema = response_factory(self.get_one_schema, name="GetOne")
83
+
84
+ func_type = inspect.signature(self.destroy_tree).return_annotation
85
+ if func_type != inspect._empty and func_type is not None:
86
+ self.delete_tree_response_schema = func_type
87
+ if self.delete_tree_response_schema:
88
+ self.delete_tree_response_schema_factory = response_factory(self.delete_tree_response_schema, name="DeleteTree")
89
+ else:
90
+ self.delete_tree_response_schema_factory = self.gen_get_one_response_schema_factory()
91
+
84
92
  doc = self.destroy_tree.__doc__
85
93
  summary = doc.strip().split("\n")[0] if doc else "Delete Tree"
86
94
  path = f"/{settings.app_settings.ROUTER_RECURSION_DELETE_SUFFIX_FIELD}" if settings.app_settings.ROUTER_WHETHER_ADD_SUFFIX else ""
@@ -88,7 +96,7 @@ class DeleteTreeView(BaseView):
88
96
  path=path,
89
97
  endpoint=self._delete_tree_decorator(),
90
98
  methods=["DELETE"],
91
- response_model=Optional[self.get_one_response_schema],
99
+ response_model=Optional[self.delete_tree_response_schema_factory],
92
100
  summary=summary,
93
101
  dependencies=self.delete_tree_route,
94
102
  )
@@ -1,3 +1,4 @@
1
+ import inspect
1
2
  import time
2
3
  from typing import Optional, Type, Any, Union
3
4
 
@@ -20,9 +21,11 @@ class DeleteView(BaseView):
20
21
 
21
22
  delete_route: Union[bool, DEPENDENCIES] = True
22
23
  delete_schema: Optional[Type[BaseModel]] = IdList
24
+ delete_response_schema: Optional[Type[BaseModel]] = IdList
23
25
  """
24
26
  delete_route: 删除路由开关,可以放依赖函数列表
25
27
  delete_schema: 删除请求模型
28
+ delete_response_schema: 删除返回模型
26
29
  """
27
30
 
28
31
  @atomic()
@@ -67,10 +70,15 @@ class DeleteView(BaseView):
67
70
  def _handler_delete_settings(self):
68
71
  if not self.delete_route:
69
72
  return
70
- if not hasattr(self, "get_one_schema"):
71
- self.get_one_schema = get_one_schema_factory(model_class=self.model_class)
72
- if not hasattr(self, "get_one_response_schema"):
73
- self.get_one_response_schema = response_factory(self.get_one_schema, name="GetOne")
73
+
74
+ func_type = inspect.signature(self.destroy).return_annotation
75
+ if func_type != inspect._empty and func_type is not None:
76
+ self.delete_response_schema = func_type
77
+ if self.delete_response_schema:
78
+ self.delete_response_schema_factory = response_factory(self.delete_response_schema, name="Delete")
79
+ else:
80
+ self.delete_response_schema_factory = self.gen_get_one_response_schema_factory()
81
+
74
82
  doc = self.destroy.__doc__
75
83
  summary = doc.strip().split("\n")[0] if doc else "Delete All"
76
84
  path = f"/{settings.app_settings.ROUTER_DELETE_SUFFIX_FIELD}" if settings.app_settings.ROUTER_WHETHER_ADD_SUFFIX else ""
@@ -78,7 +86,7 @@ class DeleteView(BaseView):
78
86
  path=path,
79
87
  endpoint=self._delete_decorator(),
80
88
  methods=["DELETE"],
81
- response_model=Optional[self.get_one_response_schema],
89
+ response_model=Optional[self.delete_response_schema_factory],
82
90
  summary=summary,
83
91
  dependencies=self.delete_route,
84
92
  )
@@ -1,3 +1,4 @@
1
+ import inspect
1
2
  from typing import Union, Optional, Type, cast, List, Any, Callable, Coroutine
2
3
 
3
4
  from fastapi import Depends, Query
@@ -22,7 +23,7 @@ from fastgenerateapi.deps import paginator_deps, filter_params_deps
22
23
  from fastgenerateapi.deps.filter_params_deps import search_params_deps
23
24
  from fastgenerateapi.schemas_factory import get_all_schema_factory, get_page_schema_factory, get_one_schema_factory, \
24
25
  response_factory
25
- from fastgenerateapi.schemas_factory.get_all_schema_factory import get_list_schema_factory
26
+ from fastgenerateapi.schemas_factory.get_all_schema_factory import get_list_schema_factory, hasattr_get_all_schema
26
27
  from fastgenerateapi.settings.all_settings import settings
27
28
 
28
29
 
@@ -49,7 +50,7 @@ class GetAllView(BaseView, GetMixin):
49
50
  auto_add_id_order: 是否自动在 order_by_fields 后面追加id排序
50
51
  """
51
52
 
52
- async def get_all(self, search: Optional[str], filters: dict, *args, **kwargs) -> Union[BaseModel, dict, None]:
53
+ async def get_all(self, search: Optional[str], filters: dict, *args, **kwargs):
53
54
  queryset = await self.get_queryset(search=search, filters=filters, *args, **kwargs)
54
55
 
55
56
  return await self.pagination_data(queryset=queryset, *args, **kwargs)
@@ -169,21 +170,25 @@ class GetAllView(BaseView, GetMixin):
169
170
  return
170
171
  self.search_controller = SearchController(self.get_base_filter(self.search_fields))
171
172
  self.filter_controller = FilterController(self.get_base_filter(self.filter_fields, self.filter_schema))
172
- get_all_schema_include = []
173
- if self.prefetch_related_fields:
174
- for key, value in self.prefetch_related_fields.items():
175
- if value and type(value) in [list, tuple, set]:
176
- for val in value:
177
- val_str = val
178
- if type(val) in [list, tuple, set]:
179
- val_str = val[0]
180
- get_all_schema_include.append(key + "__" + val_str)
181
- self.get_all_schema = self.get_all_schema or get_all_schema_factory(
182
- self.model_class, include=get_all_schema_include
183
- ) or self.get_one_schema if hasattr(self, "get_one_schema") else get_one_schema_factory(self.model_class)
173
+
174
+ func_type = inspect.signature(self.get_all).return_annotation
175
+ if func_type != inspect._empty and func_type is not None:
176
+ self.get_all_schema = func_type
177
+ if not self.get_all_schema:
178
+ get_all_schema_include = []
179
+ if self.prefetch_related_fields:
180
+ for key, value in self.prefetch_related_fields.items():
181
+ if value and type(value) in [list, tuple, set]:
182
+ for val in value:
183
+ val_str = val
184
+ if type(val) in [list, tuple, set]:
185
+ val_str = val[0]
186
+ get_all_schema_include.append(key + "__" + val_str)
187
+ self.get_all_schema = get_all_schema_factory(self.model_class, include=get_all_schema_include) \
188
+ if (get_all_schema_include or hasattr_get_all_schema(self.model_class)) else self.gen_get_one_response_schema()
184
189
  self.get_page_schema = get_page_schema_factory(self.get_all_schema)
185
190
  self.get_list_schema = get_list_schema_factory(self.get_all_schema)
186
- self.get_all_response_schema = response_factory(self.get_page_schema, name="GetPage")
191
+ self.get_all_response_schema_factory = response_factory(self.get_page_schema, name="GetPage")
187
192
  doc = self.get_all.__doc__
188
193
  summary = doc.strip().split("\n")[0] if doc else "Get All"
189
194
  path = f"/{settings.app_settings.ROUTER_GET_ALL_SUFFIX_FIELD}" if settings.app_settings.ROUTER_WHETHER_ADD_SUFFIX else ""
@@ -191,7 +196,7 @@ class GetAllView(BaseView, GetMixin):
191
196
  path=path,
192
197
  endpoint=self._get_all_decorator(),
193
198
  methods=["GET"],
194
- response_model=self.get_all_response_schema,
199
+ response_model=self.get_all_response_schema_factory,
195
200
  summary=summary,
196
201
  dependencies=self.get_all_route,
197
202
  )
@@ -1,3 +1,4 @@
1
+ import inspect
1
2
  from typing import Any, Union, Optional, Type
2
3
 
3
4
  from fastapi import Depends
@@ -66,20 +67,13 @@ class GetOneView(BaseView, GetMixin):
66
67
  def _handler_get_one_settings(self):
67
68
  if not self.get_one_route:
68
69
  return
69
- get_one_schema_include = []
70
- if self.is_with_prefetch and self.prefetch_related_fields:
71
- for key, value in self.prefetch_related_fields.items():
72
- if value and type(value) in [list, tuple, set]:
73
- for val in value:
74
- val_str = val
75
- if type(val) in [list, tuple, set]:
76
- val_str = val[0]
77
- get_one_schema_include.append(key + "__" + val_str)
78
- self.get_one_schema = self.schema or self.get_one_schema or get_one_schema_factory(
79
- model_class=self.model_class,
80
- include=get_one_schema_include,
81
- )
82
- self.get_one_response_schema = response_factory(self.get_one_schema, name="GetOne")
70
+
71
+ func_type = inspect.signature(self.get_one).return_annotation
72
+ if func_type != inspect._empty and func_type is not None:
73
+ self.get_one_schema = func_type
74
+ if not self.get_one_schema:
75
+ self.get_one_schema = self.gen_get_one_response_schema()
76
+ self.get_one_response_schema_factory = response_factory(self.get_one_schema, name="GetOne")
83
77
  doc = self.get_one.__doc__
84
78
  summary = doc.strip().split("\n")[0] if self.get_one.__doc__ else "Get One"
85
79
  path = f"/{settings.app_settings.ROUTER_GET_ONE_SUFFIX_FIELD}/{'{pk}'}" if settings.app_settings.ROUTER_WHETHER_ADD_SUFFIX else "/{pk}"
@@ -87,7 +81,7 @@ class GetOneView(BaseView, GetMixin):
87
81
  path=path,
88
82
  endpoint=self._get_one_decorator(),
89
83
  methods=["GET"],
90
- response_model=self.get_one_response_schema,
84
+ response_model=self.get_one_response_schema_factory,
91
85
  summary=summary,
92
86
  dependencies=self.get_one_route,
93
87
  error_responses=[NOT_FOUND],
@@ -1,3 +1,4 @@
1
+ import inspect
1
2
  from typing import Union, Optional, Type, cast, List, Any
2
3
 
3
4
  from fastapi import Depends, Query
@@ -53,7 +54,7 @@ class GetRelationView(BaseView):
53
54
  relation_order_by_fields: 多对多关联表排序对应字段
54
55
  """
55
56
 
56
- async def get_relation(self, pk: str, search: str, filters: dict, relation_filters: dict, *args, **kwargs) -> Union[BaseModel, dict, None]:
57
+ async def get_relation(self, pk: str, search: str, filters: dict, relation_filters: dict, *args, **kwargs):
57
58
  relation_queryset = await self.get_relation_queryset(filters=relation_filters, *args, **kwargs)
58
59
  id_list = relation_queryset.filter(eval(f"Q({self.path_id_name}='{pk}')")).values_list(self.relation_id_name, flat=True)
59
60
 
@@ -183,10 +184,14 @@ class GetRelationView(BaseView):
183
184
  self.search_controller = SearchController(self.get_base_filter(self.search_fields))
184
185
  self.filter_controller = FilterController(self.get_base_filter(self.filter_fields))
185
186
  self.filter_relation_controller = FilterController(self.get_base_filter(self.relation_filter_fields))
187
+
188
+ func_type = inspect.signature(self.get_relation).return_annotation
189
+ if func_type != inspect._empty and func_type is not None:
190
+ self.get_relation_schema = func_type
186
191
  self.get_relation_schema = self.get_relation_schema or get_relation_schema_factory(self.model_class)
187
192
  self.get_relation_page_schema = get_page_schema_factory(self.get_relation_schema)
188
193
  self.get_relation_list_schema = get_list_schema_factory(self.get_relation_schema)
189
- self.get_relation_response_schema = response_factory(self.get_relation_page_schema, name="GetPage")
194
+ self.get_relation_response_schema_factory = response_factory(self.get_relation_page_schema, name="GetPage")
190
195
  doc = self.get_relation.__doc__
191
196
  summary = doc.strip().split("\n")[0] if doc else f"Get {self.model_class.__name__.title()}"
192
197
  path = f"/get-{self.relation_id_name.removesuffix('_id')}-by-{self.path_id_name.removesuffix('_id')}/{'{pk}'}" if settings.app_settings.ROUTER_WHETHER_ADD_SUFFIX else ""
@@ -194,7 +199,7 @@ class GetRelationView(BaseView):
194
199
  path=path,
195
200
  endpoint=self._get_relation_decorator(),
196
201
  methods=["GET"],
197
- response_model=self.get_relation_response_schema,
202
+ response_model=self.get_relation_response_schema_factory,
198
203
  summary=summary,
199
204
  dependencies=self.get_relation_route,
200
205
  )
@@ -1,3 +1,4 @@
1
+ import inspect
1
2
  from typing import Union, Optional, Type, cast, List, Any, Callable, Coroutine
2
3
 
3
4
  from fastapi import Depends, Query
@@ -56,7 +57,7 @@ class GetTreeView(BaseView):
56
57
  search: str,
57
58
  filters: dict,
58
59
  request, *args, **kwargs
59
- ) -> Union[BaseModel, dict, None]:
60
+ ):
60
61
  if settings.app_settings.METHOD_TREE_CHOICE.upper() == "MAP":
61
62
  data_list = await self.map_method(
62
63
  node_id=node_id, search=search, filters=filters, request=request, *args, **kwargs)
@@ -177,9 +178,13 @@ class GetTreeView(BaseView):
177
178
  return
178
179
  self.search_controller = SearchController(self.get_base_filter(self.search_fields))
179
180
  self.filter_controller = FilterController(self.get_base_filter(self.filter_fields))
181
+
182
+ func_type = inspect.signature(self.get_tree).return_annotation
183
+ if func_type != inspect._empty and func_type is not None:
184
+ self.get_tree_schema = func_type
180
185
  self.get_tree_schema = self.get_tree_schema or get_tree_schema_factory(self.model_class)
181
186
  self.get_tree_data_schema = get_list_schema_factory(self.get_tree_schema)
182
- self.get_tree_response_schema = response_factory(self.get_tree_data_schema, name="GetTree")
187
+ self.get_tree_response_schema_factory = response_factory(self.get_tree_data_schema, name="GetTree")
183
188
  doc = self.get_tree.__doc__
184
189
  summary = doc.strip().split("\n")[0] if self.get_tree.__doc__ else "Get Tree"
185
190
  path = f"/{settings.app_settings.ROUTER_GET_TREE_SUFFIX_FIELD}" if settings.app_settings.ROUTER_WHETHER_ADD_SUFFIX else ""
@@ -187,7 +192,7 @@ class GetTreeView(BaseView):
187
192
  path=path,
188
193
  endpoint=self._get_tree_decorator(),
189
194
  methods=["GET"],
190
- response_model=self.get_tree_response_schema,
195
+ response_model=self.get_tree_response_schema_factory,
191
196
  summary=summary,
192
197
  dependencies=self.get_tree_route,
193
198
  )
@@ -59,10 +59,7 @@ class SwitchView(BaseView):
59
59
  def _handler_switch_route_settings(self):
60
60
  if not self.switch_route_fields:
61
61
  return
62
- if not hasattr(self, "get_one_schema"):
63
- self.get_one_schema = get_one_schema_factory(model_class=self.model_class)
64
- if not hasattr(self, "get_one_response_schema"):
65
- self.get_one_response_schema = response_factory(self.get_one_schema, name="GetOne")
62
+
66
63
  for switch_route_field in self.switch_route_fields:
67
64
  if self.model_class._meta.fields_map.get(switch_route_field).field_type not in [bool, int]:
68
65
  self.error(msg=f"{switch_route_field} is not bool or int")
@@ -72,7 +69,7 @@ class SwitchView(BaseView):
72
69
  path="/%s/{pk}" % ("switch_"+switch_route_field),
73
70
  endpoint=self._switch_decorator(switch_route_field),
74
71
  methods=["PUT"],
75
- response_model=self.get_one_response_schema,
72
+ response_model=self.gen_get_one_response_schema_factory(),
76
73
  summary=summary,
77
74
  dependencies=True,
78
75
  error_responses=[NOT_FOUND],
@@ -1,3 +1,4 @@
1
+ import inspect
1
2
  from typing import Optional, Type, Union, Any
2
3
 
3
4
  from fastapi import Depends
@@ -23,6 +24,7 @@ class UpdateRelationView(BaseView, SaveMixin):
23
24
  path_id_name: str
24
25
  relation_id_name: str
25
26
  update_relation_schema: Optional[Type[BaseModel]] = IdList
27
+ update_relation_response_schema: Optional[Type[BaseModel]] = None
26
28
  update_relation_route: Union[bool, DEPENDENCIES] = True
27
29
  """
28
30
  path_id_name: 路径id在模型中对应的字段名
@@ -72,7 +74,12 @@ class UpdateRelationView(BaseView, SaveMixin):
72
74
  def _handler_update_relation_settings(self):
73
75
  if not self.update_relation_route:
74
76
  return
75
- self.update_relation_response_schema = response_factory(name="UpdateRelation")
77
+
78
+ func_type = inspect.signature(self.create).return_annotation
79
+ if func_type != inspect._empty and func_type is not None:
80
+ self.update_relation_response_schema = func_type
81
+ self.update_relation_response_schema_factory = response_factory(self.update_relation_response_schema, name="UpdateRelation")
82
+
76
83
  doc = self.update_relation.__doc__
77
84
  summary = doc.strip().split("\n")[0] if doc else f"Update {self.model_class.__name__.title()}"
78
85
  path = f"/update-{self.relation_id_name.removesuffix('_id')}-by-{self.path_id_name.removesuffix('_id')}/{'{pk}'}" if settings.app_settings.ROUTER_WHETHER_ADD_SUFFIX else "/{pk}"
@@ -80,7 +87,7 @@ class UpdateRelationView(BaseView, SaveMixin):
80
87
  path=path,
81
88
  endpoint=self._update_relation_decorator(),
82
89
  methods=["PUT"],
83
- response_model=self.update_relation_response_schema,
90
+ response_model=self.update_relation_response_schema_factory,
84
91
  summary=summary,
85
92
  dependencies=self.update_relation_route,
86
93
  error_responses=[NOT_FOUND],
@@ -1,3 +1,4 @@
1
+ import inspect
1
2
  from typing import Optional, Type, Union, Any
2
3
 
3
4
  from fastapi import Depends
@@ -21,6 +22,7 @@ from fastgenerateapi.utils.exception import NOT_FOUND
21
22
  class UpdateView(BaseView, SaveMixin):
22
23
 
23
24
  update_schema: Optional[Type[BaseModel]] = None
25
+ update_response_schema: Optional[Type[BaseModel]] = None
24
26
  update_route: Union[bool, DEPENDENCIES] = True
25
27
  """
26
28
  update_schema: 修改请求模型
@@ -81,10 +83,15 @@ class UpdateView(BaseView, SaveMixin):
81
83
  if not self.update_route:
82
84
  return
83
85
  self.update_schema = self.update_schema or update_schema_factory(self.model_class)
84
- if not hasattr(self, "get_one_schema"):
85
- self.get_one_schema = get_one_schema_factory(model_class=self.model_class)
86
- if not hasattr(self, "get_one_response_schema"):
87
- self.get_one_response_schema = response_factory(self.get_one_schema, name="GetOne")
86
+
87
+ func_type = inspect.signature(self.update).return_annotation
88
+ if func_type != inspect._empty and func_type is not None:
89
+ self.update_response_schema = func_type
90
+ if self.update_response_schema:
91
+ self.update_response_schema_factory = response_factory(self.update_response_schema, name="Update")
92
+ else:
93
+ self.update_response_schema_factory = self.gen_get_one_response_schema_factory()
94
+
88
95
  doc = self.update.__doc__
89
96
  summary = doc.strip().split("\n")[0] if doc else f"Update"
90
97
  path = f"/{settings.app_settings.ROUTER_UPDATE_SUFFIX_FIELD}/{'{pk}'}" if settings.app_settings.ROUTER_WHETHER_ADD_SUFFIX else "/{pk}"
@@ -92,7 +99,7 @@ class UpdateView(BaseView, SaveMixin):
92
99
  path=path,
93
100
  endpoint=self._update_decorator(),
94
101
  methods=["PUT"],
95
- response_model=self.get_one_response_schema,
102
+ response_model=self.update_response_schema_factory,
96
103
  summary=summary,
97
104
  dependencies=self.update_route,
98
105
  error_responses=[NOT_FOUND],
@@ -11,6 +11,13 @@ from fastgenerateapi.schemas_factory.common_function import get_dict_from_model_
11
11
  from fastgenerateapi.settings.all_settings import settings
12
12
 
13
13
 
14
+ def hasattr_get_all_schema(model_class: Type[Model],):
15
+ if not hasattr(model_class, "PydanticMeta"):
16
+ return False
17
+ if hasattr(model_class.PydanticMeta, "get_all_include") or hasattr(model_class.PydanticMeta, "get_all_exclude"):
18
+ return True
19
+ return False
20
+
14
21
  def get_all_schema_factory(
15
22
  model_class: Type[Model],
16
23
  include: Union[list, tuple, set] = None,
@@ -21,40 +28,37 @@ def get_all_schema_factory(
21
28
  """
22
29
  Is used to create a GetAllSchema
23
30
  """
24
- if not hasattr(model_class, "PydanticMeta"):
25
- return None
26
- if not include and not extra_include and not exclude and not hasattr(model_class.PydanticMeta, "get_all_include") and not hasattr(model_class.PydanticMeta, "get_all_exclude"):
27
- return None
28
-
29
31
  all_fields_info = get_dict_from_model_fields(model_class)
30
32
 
31
33
  include_fields = set()
32
34
  exclude_fields = set()
33
-
34
- if hasattr(model_class.PydanticMeta, "include"):
35
- include_fields_dict = get_dict_from_pydanticmeta(model_class, model_class.PydanticMeta.include)
36
- all_fields_info.update(include_fields_dict)
37
- include_fields.update(include_fields_dict.keys())
35
+ if hasattr(model_class, "PydanticMeta"):
36
+ if hasattr(model_class.PydanticMeta, "include"):
37
+ include_fields_dict = get_dict_from_pydanticmeta(model_class, model_class.PydanticMeta.include)
38
+ all_fields_info.update(include_fields_dict)
39
+ include_fields.update(include_fields_dict.keys())
40
+ else:
41
+ include_fields.update(all_fields_info.keys())
42
+ if hasattr(model_class.PydanticMeta, "exclude"):
43
+ exclude_fields.update(model_class.PydanticMeta.exclude)
44
+
45
+ if hasattr(model_class.PydanticMeta, "get_include"):
46
+ get_include_fields_dict = get_dict_from_pydanticmeta(model_class, model_class.PydanticMeta.get_include)
47
+ all_fields_info.update(get_include_fields_dict)
48
+ include_fields.update(get_include_fields_dict.keys())
49
+ if hasattr(model_class.PydanticMeta, "get_exclude"):
50
+ exclude_fields.update(model_class.PydanticMeta.get_exclude)
51
+
52
+ # get_all_include
53
+ if hasattr(model_class.PydanticMeta, "get_all_include"):
54
+ get_all_include_fields_dict = get_dict_from_pydanticmeta(model_class, model_class.PydanticMeta.get_all_include)
55
+ all_fields_info.update(get_all_include_fields_dict)
56
+ include_fields.update(get_all_include_fields_dict.keys())
57
+ # get_all_exclude
58
+ if hasattr(model_class.PydanticMeta, "get_all_exclude"):
59
+ exclude_fields.update(model_class.PydanticMeta.get_all_exclude)
38
60
  else:
39
61
  include_fields.update(all_fields_info.keys())
40
- if hasattr(model_class.PydanticMeta, "exclude"):
41
- exclude_fields.update(model_class.PydanticMeta.exclude)
42
-
43
- if hasattr(model_class.PydanticMeta, "get_include"):
44
- get_include_fields_dict = get_dict_from_pydanticmeta(model_class, model_class.PydanticMeta.get_include)
45
- all_fields_info.update(get_include_fields_dict)
46
- include_fields.update(get_include_fields_dict.keys())
47
- if hasattr(model_class.PydanticMeta, "get_exclude"):
48
- exclude_fields.update(model_class.PydanticMeta.get_exclude)
49
-
50
- # get_all_include
51
- if hasattr(model_class.PydanticMeta, "get_all_include"):
52
- get_all_include_fields_dict = get_dict_from_pydanticmeta(model_class, model_class.PydanticMeta.get_all_include)
53
- all_fields_info.update(get_all_include_fields_dict)
54
- include_fields.update(get_all_include_fields_dict.keys())
55
- # get_all_exclude
56
- if hasattr(model_class.PydanticMeta, "get_all_exclude"):
57
- exclude_fields.update(model_class.PydanticMeta.get_all_exclude)
58
62
 
59
63
  # 参数处理
60
64
  if include:
@@ -4,4 +4,5 @@ from .db_settings import *
4
4
  from .file_settings import *
5
5
  from .jwt_settings import *
6
6
  from .sms_settings import *
7
+ from .etcd_settings import *
7
8
 
@@ -1,7 +1,7 @@
1
1
  import os
2
2
  from functools import lru_cache
3
3
  from pathlib import Path
4
- from typing import Union, Optional, Type
4
+ from typing import Union, Optional
5
5
 
6
6
  import yaml
7
7
  from fastapi.exceptions import ValidationException
@@ -66,10 +66,7 @@ class SettingsModel(BaseModel):
66
66
  content += f" # {v.description}\n"
67
67
  content += "\n"
68
68
  if etcd_settings and etcd_settings.ETCD_SETTING_KEY:
69
- import etcd3
70
- etcd_dict = etcd_settings.model_dump(exclude_unset=True, by_alias=True, exclude={"ETCD_SETTING_KEY", })
71
- etcd = etcd3.client(**{key.removeprefix("ETCD_").lower(): value for key, value in etcd_dict.items()})
72
- etcd.put(etcd_settings.ETCD_SETTING_KEY, content)
69
+ etcd_settings.client.put(etcd_settings.ETCD_SETTING_KEY, content)
73
70
  else:
74
71
  with open(file=path, mode='w', encoding='utf-8') as f:
75
72
  f.writelines(content)
@@ -78,42 +75,47 @@ class SettingsModel(BaseModel):
78
75
  @lru_cache
79
76
  def get_global_settings(
80
77
  cls,
81
- path: Union[Path, str, None] = '.env',
82
- etcd_settings: Optional[EtcdSettings] = None,
78
+ path: Union[Path, str, None] = None,
83
79
  ):
84
80
  """
85
81
  get global settings and set into cache
86
- :param path: 可选 .env / application.yaml / etcd.yaml
87
- :param etcd_settings: 当储配置 存在etcd 时
82
+ :param path:
83
+ None时,自动检测本地文件,优先级 application.yaml,.env
84
+ 推荐参数 .env / application.yaml / etcd.yaml
88
85
  :return:
89
86
  """
90
- setting_models = cls.model_fields.copy()
87
+ is_yaml = False
88
+ if path and str(path).__contains__('.yaml'):
89
+ is_yaml = True
90
+ elif os.path.isfile("application.yaml"):
91
+ is_yaml = True
91
92
 
93
+ setting_models = cls.model_fields.copy()
92
94
  setting_dict = {}
93
- if str(path).__contains__('.env'):
95
+ if not is_yaml:
94
96
  for k, v in setting_models.items():
95
97
  if isinstance(v, FieldInfo):
96
98
  setting_dict[k] = v.annotation(_env_file=str(path))
97
- elif str(path).__contains__('.yaml'):
98
- data_dict = None
99
+ else:
100
+ data_dict = {}
99
101
  if os.path.isfile(path):
100
102
  with open(path, 'r', encoding='utf-8') as file:
101
- data_dict = yaml.safe_load(file)
102
- else:
103
- if not etcd_settings:
104
- etcd_settings = EtcdSettings()
105
- if etcd_settings.ETCD_SETTING_KEY:
106
- import etcd3
107
- etcd_dict = etcd_settings.model_dump(exclude_unset=True, by_alias=True, exclude={"ETCD_SETTING_KEY",})
108
- etcd = etcd3.client(**{key.removeprefix("ETCD_").lower(): value for key, value in etcd_dict.items()})
109
- res, metadata = etcd.get(etcd_settings.ETCD_SETTING_KEY)
110
- data_dict = yaml.safe_load(res)
103
+ data_dict = yaml.safe_load(file) or {}
104
+ etcd_settings = EtcdSettings(**data_dict.get("EtcdSettings", {}))
105
+ if etcd_settings.ETCD_SETTING_KEY:
106
+ res, metadata = etcd_settings.client.get(etcd_settings.ETCD_SETTING_KEY)
107
+ data_dict.update(yaml.safe_load(res))
111
108
  if not data_dict:
112
109
  raise ValidationException(errors="配置错误")
113
110
  for k, v in setting_models.items():
114
111
  if isinstance(v, FieldInfo):
112
+ env_prefix = None
115
113
  if hasattr(v.annotation, "Config") and v.annotation.Config.env_prefix:
116
- annotation_dict = {k_i.removeprefix(v.annotation.Config.env_prefix): v_i for k_i, v_i in data_dict.get(v.annotation.__name__, {}).items()}
114
+ env_prefix = v.annotation.Config.env_prefix
115
+ if not env_prefix and hasattr(v.annotation, "model_config"):
116
+ env_prefix = v.annotation.model_config.get("env_prefix")
117
+ if env_prefix:
118
+ annotation_dict = {k_i.removeprefix(env_prefix): v_i for k_i, v_i in data_dict.get(v.annotation.__name__, {}).items()}
117
119
  else:
118
120
  annotation_dict = data_dict.get(v.annotation.__name__, {})
119
121
  setting_dict[k] = v.annotation(**annotation_dict)
@@ -125,6 +127,14 @@ class SettingsModel(BaseModel):
125
127
  settings.redis_settings = setting_data.redis_settings
126
128
  return setting_data
127
129
 
130
+ def watch(self):
131
+ """
132
+ 监听文件或这etcd变化,待完善
133
+ 借用 etcd.watch(target)
134
+ :return:
135
+ """
136
+ ...
137
+
128
138
 
129
139
  settings = SettingsModel()
130
140
 
@@ -11,7 +11,7 @@ class DBSettings(BaseSettings):
11
11
 
12
12
  DB_TYPE: Optional[str] = Field(default='mysql', description="数据库类型")
13
13
  DB_HOST: Optional[str] = Field(default='127.0.0.1', description="数据库域名")
14
- DB_PORT: Optional[str] = Field(default='3306', description="数据库端口")
14
+ DB_PORT: Optional[int] = Field(default='3306', description="数据库端口")
15
15
  DB_DATABASE: Optional[str] = Field(default='admin', description="数据库名")
16
16
  DB_USERNAME: Optional[str] = Field(default='root', description="数据库用户名")
17
17
  DB_PASSWORD: Optional[str] = Field(default='', description="数据库密码")
@@ -27,6 +27,13 @@ class EtcdSettings(BaseSettings):
27
27
  frozen=True,
28
28
  )
29
29
 
30
+ @property
31
+ def client(self):
32
+ import etcd3
33
+ etcd_dict = self.model_dump(exclude_unset=True, by_alias=True, exclude={"ETCD_SETTING_KEY", })
34
+ etcd = etcd3.client(**{key.removeprefix("ETCD_").lower(): value for key, value in etcd_dict.items()})
35
+
36
+ return etcd
30
37
 
31
38
 
32
39
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fastgenerateapi
3
- Version: 1.1.20
3
+ Version: 1.1.24
4
4
  Summary: FastAPIView Class View
5
5
  Author: ShiLiang
6
6
  Author-email: 2509144896@qq.com