fastgenerateapi 0.0.27__py2.py3-none-any.whl → 1.1.6__py2.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.

Potentially problematic release.


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

Files changed (85) hide show
  1. fastgenerateapi/__init__.py +2 -2
  2. fastgenerateapi/__version__.py +1 -1
  3. fastgenerateapi/api_view/base_view.py +17 -7
  4. fastgenerateapi/api_view/create_view.py +1 -1
  5. fastgenerateapi/api_view/delete_filter_view.py +1 -1
  6. fastgenerateapi/api_view/delete_tree_view.py +3 -3
  7. fastgenerateapi/api_view/delete_view.py +3 -3
  8. fastgenerateapi/api_view/get_all_view.py +21 -17
  9. fastgenerateapi/api_view/get_one_view.py +1 -1
  10. fastgenerateapi/api_view/get_relation_view.py +1 -1
  11. fastgenerateapi/api_view/get_tree_view.py +1 -1
  12. fastgenerateapi/api_view/mixin/base_mixin.py +11 -7
  13. fastgenerateapi/api_view/mixin/dbmodel_mixin.py +30 -20
  14. fastgenerateapi/api_view/mixin/response_mixin.py +79 -32
  15. fastgenerateapi/api_view/mixin/tool_mixin.py +1 -357
  16. fastgenerateapi/api_view/mixin/utils/__init__.py +0 -0
  17. fastgenerateapi/api_view/mixin/utils/docx_util.py +399 -0
  18. fastgenerateapi/api_view/mixin/utils/file_util.py +30 -0
  19. fastgenerateapi/api_view/mixin/utils/pdf_util.py +76 -0
  20. fastgenerateapi/api_view/mixin/utils/xlsx_util.py +336 -0
  21. fastgenerateapi/api_view/mixin/utils/zip_util.py +50 -0
  22. fastgenerateapi/api_view/switch_view.py +11 -11
  23. fastgenerateapi/api_view/update_relation_view.py +3 -3
  24. fastgenerateapi/api_view/update_view.py +1 -1
  25. fastgenerateapi/cache/cache_decorator.py +1 -1
  26. fastgenerateapi/controller/filter_controller.py +68 -26
  27. fastgenerateapi/controller/router_controller.py +9 -9
  28. fastgenerateapi/controller/rpc_controller.py +1 -1
  29. fastgenerateapi/controller/ws_controller.py +1 -1
  30. fastgenerateapi/deps/filter_params_deps.py +34 -4
  31. fastgenerateapi/deps/paginator_deps.py +4 -4
  32. fastgenerateapi/deps/tree_params_deps.py +4 -4
  33. fastgenerateapi/example/models.py +3 -2
  34. fastgenerateapi/example/schemas.py +1 -1
  35. fastgenerateapi/example/views.py +1 -1
  36. fastgenerateapi/fastapi_utils/__init__.py +0 -0
  37. fastgenerateapi/fastapi_utils/all.py +5 -0
  38. fastgenerateapi/fastapi_utils/param_utils.py +37 -0
  39. fastgenerateapi/fastapi_utils/response_utils.py +344 -0
  40. fastgenerateapi/model/__init__.py +0 -0
  41. fastgenerateapi/model/base_model.py +56 -0
  42. fastgenerateapi/my_fields/enum_field.py +8 -8
  43. fastgenerateapi/my_fields/pk_field.py +1 -1
  44. fastgenerateapi/my_fields/soft_delete_field.py +4 -3
  45. fastgenerateapi/my_fields/validator.py +60 -0
  46. fastgenerateapi/pydantic_utils/base_model.py +54 -21
  47. fastgenerateapi/pydantic_utils/base_settings.py +16 -0
  48. fastgenerateapi/pydantic_utils/json_encoders.py +2 -1
  49. fastgenerateapi/schemas_factory/common_function.py +1 -1
  50. fastgenerateapi/schemas_factory/common_schema_factory.py +4 -4
  51. fastgenerateapi/schemas_factory/create_schema_factory.py +4 -4
  52. fastgenerateapi/schemas_factory/filter_schema_factory.py +6 -6
  53. fastgenerateapi/schemas_factory/get_all_schema_factory.py +5 -5
  54. fastgenerateapi/schemas_factory/get_one_schema_factory.py +4 -3
  55. fastgenerateapi/schemas_factory/get_relation_schema_factory.py +3 -3
  56. fastgenerateapi/schemas_factory/get_tree_schema_factory.py +3 -3
  57. fastgenerateapi/schemas_factory/response_factory.py +5 -10
  58. fastgenerateapi/schemas_factory/sql_get_all_schema_factory.py +3 -3
  59. fastgenerateapi/schemas_factory/update_schema_factory.py +4 -4
  60. fastgenerateapi/settings/__init__.py +6 -0
  61. fastgenerateapi/settings/all_settings.py +91 -0
  62. fastgenerateapi/settings/{settings.py → app_settings.py} +31 -28
  63. fastgenerateapi/settings/db_settings.py +69 -0
  64. fastgenerateapi/settings/file_settings.py +24 -0
  65. fastgenerateapi/settings/jwt_settings.py +23 -0
  66. fastgenerateapi/settings/otlp_settings.py +69 -0
  67. fastgenerateapi/settings/redis_settings.py +16 -0
  68. fastgenerateapi/settings/sms_settings.py +25 -0
  69. fastgenerateapi/settings/system_settings.py +30 -0
  70. fastgenerateapi/utils/auto_discover.py +61 -0
  71. fastgenerateapi/utils/file_utils.py +76 -0
  72. fastgenerateapi/utils/pwd_utils.py +49 -0
  73. fastgenerateapi/utils/ramdom_utils.py +48 -0
  74. fastgenerateapi/utils/snowflake.py +23 -20
  75. fastgenerateapi/utils/str_util.py +120 -0
  76. fastgenerateapi/utils/swagger_to_js.py +26 -0
  77. {fastgenerateapi-0.0.27.dist-info → fastgenerateapi-1.1.6.dist-info}/METADATA +61 -24
  78. fastgenerateapi-1.1.6.dist-info/RECORD +109 -0
  79. {fastgenerateapi-0.0.27.dist-info → fastgenerateapi-1.1.6.dist-info}/WHEEL +1 -1
  80. {fastgenerateapi-0.0.27.dist-info → fastgenerateapi-1.1.6.dist-info}/top_level.txt +1 -0
  81. script/__init__.py +2 -0
  82. fastgenerateapi/settings/register_settings.py +0 -6
  83. fastgenerateapi/utils/parse_str.py +0 -36
  84. fastgenerateapi-0.0.27.dist-info/RECORD +0 -82
  85. {fastgenerateapi-0.0.27.dist-info → fastgenerateapi-1.1.6.dist-info}/LICENSE +0 -0
@@ -23,6 +23,6 @@ from fastgenerateapi.api_view.update_relation_view import UpdateRelationView
23
23
  from fastgenerateapi.channel.websocket_view import WebsocketView
24
24
  from fastgenerateapi.channel.consumer import Consumer
25
25
 
26
- # 查看配置模型
27
- from fastgenerateapi.settings.settings import SettingsModel
26
+ # 模型相关类
27
+ from fastgenerateapi.pydantic_utils.base_model import model_config, BaseModel, IdList
28
28
 
@@ -8,7 +8,7 @@
8
8
  # d8888P
9
9
 
10
10
 
11
- VERSION = (0, 0, 27)
11
+ VERSION = (1, 1, 6)
12
12
 
13
13
  __version__ = '.'.join(map(str, VERSION))
14
14
 
@@ -15,7 +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.settings.register_settings import settings
18
+ from fastgenerateapi.settings.all_settings import settings
19
19
  from fastgenerateapi.utils.exception import NOT_FOUND
20
20
 
21
21
 
@@ -93,10 +93,17 @@ class BaseView(BaseMixin, ResponseMixin, ToolMixin, DBModelMixin):
93
93
  return result
94
94
 
95
95
  async def delete_queryset(self, queryset: QuerySet):
96
-
97
- await queryset.update(**{
98
- settings.app_settings.WHETHER_DELETE_FIELD: self._delete_value()
99
- })
96
+ """
97
+ 考虑到不一定会集成已有的模型,删除根据是否存在字段来判断
98
+ :param queryset:
99
+ :return:
100
+ """
101
+ if settings.app_settings.WHETHER_DELETE_FIELD in queryset.fields:
102
+ await queryset.update(**{
103
+ settings.app_settings.WHETHER_DELETE_FIELD: self._delete_value()
104
+ })
105
+ else:
106
+ await queryset.delete()
100
107
 
101
108
  @staticmethod
102
109
  async def setattr_model(model: Model, prefetch_related_fields, *args, **kwargs) -> Model:
@@ -137,8 +144,11 @@ class BaseView(BaseMixin, ResponseMixin, ToolMixin, DBModelMixin):
137
144
  attr_model = getattr(attr_model, attr_key, None)
138
145
  model_dict[field[1]] = attr_model
139
146
  model_fields[field[1]] = (type(attr_model), ...)
140
- schema = create_model(__model_name=f"{Model.__name__}{uuid.uuid4()}", **model_fields)
141
- return schema.parse_obj(model_dict)
147
+ schema = create_model(
148
+ f"{Model.__name__}{uuid.uuid4()}",
149
+ **model_fields
150
+ )
151
+ return schema.model_validate(model_dict)
142
152
 
143
153
  async def check_unique_field(
144
154
  self,
@@ -11,7 +11,7 @@ from fastgenerateapi.api_view.base_view import BaseView
11
11
  from fastgenerateapi.api_view.mixin.save_mixin import SaveMixin
12
12
  from fastgenerateapi.data_type.data_type import DEPENDENCIES
13
13
  from fastgenerateapi.schemas_factory import get_one_schema_factory, create_schema_factory, response_factory
14
- from fastgenerateapi.settings.register_settings import settings
14
+ from fastgenerateapi.settings.all_settings import settings
15
15
 
16
16
 
17
17
  class CreateView(BaseView, SaveMixin):
@@ -10,7 +10,7 @@ from fastgenerateapi.api_view.base_view import BaseView
10
10
  from fastgenerateapi.data_type.data_type import CALLABLE, DEPENDENCIES
11
11
  from fastgenerateapi.deps import filter_params_deps
12
12
  from fastgenerateapi.schemas_factory import response_factory
13
- from fastgenerateapi.settings.register_settings import settings
13
+ from fastgenerateapi.settings.all_settings import settings
14
14
 
15
15
 
16
16
  class DeleteFilterView(BaseView):
@@ -9,15 +9,15 @@ from tortoise.transactions import atomic
9
9
 
10
10
  from fastgenerateapi.api_view.base_view import BaseView
11
11
  from fastgenerateapi.data_type.data_type import CALLABLE, DEPENDENCIES
12
- from fastgenerateapi.pydantic_utils.base_model import IDList
12
+ from fastgenerateapi.pydantic_utils.base_model import IdList
13
13
  from fastgenerateapi.schemas_factory import response_factory
14
- from fastgenerateapi.settings.register_settings import settings
14
+ from fastgenerateapi.settings.all_settings import settings
15
15
 
16
16
 
17
17
  class DeleteTreeView(BaseView):
18
18
 
19
19
  delete_tree_route: Union[bool, DEPENDENCIES] = True
20
- delete_tree_schema: Optional[Type[BaseModel]] = IDList
20
+ delete_tree_schema: Optional[Type[BaseModel]] = IdList
21
21
  """
22
22
  delete_route: 删除路由开关,可以放依赖函数列表
23
23
  delete_schema: 删除请求模型
@@ -9,15 +9,15 @@ from tortoise.transactions import atomic
9
9
 
10
10
  from fastgenerateapi.api_view.base_view import BaseView
11
11
  from fastgenerateapi.data_type.data_type import CALLABLE, DEPENDENCIES
12
- from fastgenerateapi.pydantic_utils.base_model import IDList
12
+ from fastgenerateapi.pydantic_utils.base_model import IdList
13
13
  from fastgenerateapi.schemas_factory import response_factory
14
- from fastgenerateapi.settings.register_settings import settings
14
+ from fastgenerateapi.settings.all_settings import settings
15
15
 
16
16
 
17
17
  class DeleteView(BaseView):
18
18
 
19
19
  delete_route: Union[bool, DEPENDENCIES] = True
20
- delete_schema: Optional[Type[BaseModel]] = IDList
20
+ delete_schema: Optional[Type[BaseModel]] = IdList
21
21
  """
22
22
  delete_route: 删除路由开关,可以放依赖函数列表
23
23
  delete_schema: 删除请求模型
@@ -16,19 +16,20 @@ from fastgenerateapi.api_view.mixin.get_mixin import GetMixin
16
16
  from fastgenerateapi.cache.cache_decorator import get_all_cache_decorator
17
17
  from fastgenerateapi.cache.key_builder import generate_key_builder
18
18
  from fastgenerateapi.controller import SearchController, BaseFilter, FilterController
19
- from fastgenerateapi.data_type.data_type import DEPENDENCIES
19
+ from fastgenerateapi.data_type.data_type import DEPENDENCIES, PYDANTIC_SCHEMA
20
20
  from fastgenerateapi.deps import paginator_deps, filter_params_deps
21
+ from fastgenerateapi.deps.filter_params_deps import search_params_deps
21
22
  from fastgenerateapi.schemas_factory import get_all_schema_factory, get_page_schema_factory, get_one_schema_factory, \
22
23
  response_factory
23
24
  from fastgenerateapi.schemas_factory.get_all_schema_factory import get_list_schema_factory
24
- from fastgenerateapi.settings.register_settings import settings
25
+ from fastgenerateapi.settings.all_settings import settings
25
26
 
26
27
 
27
28
  class GetAllView(BaseView, GetMixin):
28
-
29
29
  get_all_route: Union[bool, DEPENDENCIES] = True
30
- get_all_schema: Optional[Type[BaseModel]] = None
30
+ get_all_schema: Optional[Type[PYDANTIC_SCHEMA]] = None
31
31
  search_fields: Union[None, list] = None
32
+ filter_schema: Optional[Type[PYDANTIC_SCHEMA]] = None
32
33
  filter_fields: Union[None, list] = None
33
34
  order_by_fields: Union[None, list] = None
34
35
  """
@@ -45,12 +46,12 @@ class GetAllView(BaseView, GetMixin):
45
46
  order_by_fields: 排序对应字段
46
47
  """
47
48
 
48
- async def get_all(self, search: str, filters: dict, *args, **kwargs) -> Union[BaseModel, dict, None]:
49
+ async def get_all(self, search: Optional[str], filters: dict, *args, **kwargs) -> Union[BaseModel, dict, None]:
49
50
  queryset = await self.get_queryset(search=search, filters=filters, *args, **kwargs)
50
51
 
51
52
  return await self.pagination_data(queryset=queryset, *args, **kwargs)
52
53
 
53
- async def get_queryset(self, search: str, filters: dict, *args, **kwargs) -> QuerySet:
54
+ async def get_queryset(self, search: Optional[str], filters: dict, *args, **kwargs) -> QuerySet:
54
55
  """
55
56
  处理search搜索;处理筛选字段;处理外键预加载;处理排序
56
57
  """
@@ -81,14 +82,15 @@ class GetAllView(BaseView, GetMixin):
81
82
  async def pagination_data(
82
83
  self,
83
84
  queryset: QuerySet,
84
- paginator,
85
+ paginator=None,
85
86
  schema: Type[BaseModel] = None,
86
87
  fields: List[Union[str, tuple]] = None,
87
88
  *args, **kwargs
88
89
  ):
89
90
 
90
91
  data_list = []
91
- if getattr(paginator, settings.app_settings.DETERMINE_WHETHER_PAGE_FIELD) == settings.app_settings.DETERMINE_PAGE_BOOL_VALUE:
92
+ if paginator is None or getattr(paginator, settings.app_settings.DETERMINE_WHETHER_PAGE_FIELD) == \
93
+ settings.app_settings.DETERMINE_PAGE_BOOL_VALUE:
92
94
  model_list = await queryset.all()
93
95
  else:
94
96
  count = await queryset.count()
@@ -112,7 +114,8 @@ class GetAllView(BaseView, GetMixin):
112
114
  else:
113
115
  data_list.append(self.get_all_schema.from_orm(model))
114
116
 
115
- if getattr(paginator, settings.app_settings.DETERMINE_WHETHER_PAGE_FIELD) == settings.app_settings.DETERMINE_PAGE_BOOL_VALUE:
117
+ if paginator is None or getattr(paginator, settings.app_settings.DETERMINE_WHETHER_PAGE_FIELD) == \
118
+ settings.app_settings.DETERMINE_PAGE_BOOL_VALUE:
116
119
  if schema or fields:
117
120
  return get_list_schema_factory()(**{settings.app_settings.LIST_RESPONSE_FIELD: data_list})
118
121
  return self.get_list_schema(**{settings.app_settings.LIST_RESPONSE_FIELD: data_list})
@@ -134,12 +137,13 @@ class GetAllView(BaseView, GetMixin):
134
137
  return getattr(page_result, settings.app_settings.LIST_RESPONSE_FIELD, [])
135
138
 
136
139
  def _get_all_decorator(self, *args: Any, **kwargs: Any) -> DecoratedCallable:
137
- @get_all_cache_decorator(cache(expire=settings.app_settings.CACHE_GET_ALL_SECONDS, coder=JsonCoder, key_builder=generate_key_builder))
140
+ @get_all_cache_decorator(cache(expire=settings.app_settings.CACHE_GET_ALL_SECONDS, coder=JsonCoder,
141
+ key_builder=generate_key_builder))
138
142
  async def route(
139
143
  request: Request,
140
144
  paginator=Depends(paginator_deps()),
141
- search: str = Query(default="", description="搜索"),
142
- filters: dict = Depends(filter_params_deps(model_class=self.model_class, fields=self.filter_fields)),
145
+ search: Optional[str] = Depends(search_params_deps(self.search_fields)),
146
+ filters: dict = Depends(filter_params_deps(model_class=self.model_class, fields=self.filter_fields, schema=self.filter_schema)),
143
147
  ) -> JSONResponse:
144
148
  data = await self.get_all(
145
149
  paginator=paginator,
@@ -150,14 +154,17 @@ class GetAllView(BaseView, GetMixin):
150
154
  **kwargs
151
155
  )
152
156
  return self.success(data=data)
157
+
153
158
  return route
154
159
 
155
160
  def _handler_get_all_settings(self):
156
161
  if not self.get_all_route:
157
162
  return
158
163
  self.search_controller = SearchController(self.get_base_filter(self.search_fields))
159
- self.filter_controller = FilterController(self.get_base_filter(self.filter_fields))
160
- self.get_all_schema = self.get_all_schema or get_all_schema_factory(self.model_class) or self.get_one_schema if hasattr(self, "get_one_schema") else get_one_schema_factory(self.model_class)
164
+ self.filter_controller = FilterController(self.get_base_filter(self.filter_fields, self.filter_schema))
165
+ self.get_all_schema = self.get_all_schema or get_all_schema_factory(
166
+ self.model_class) or self.get_one_schema if hasattr(self, "get_one_schema") else get_one_schema_factory(
167
+ self.model_class)
161
168
  self.get_page_schema = get_page_schema_factory(self.get_all_schema)
162
169
  self.get_list_schema = get_list_schema_factory(self.get_all_schema)
163
170
  self.get_all_response_schema = response_factory(self.get_page_schema, name="GetPage")
@@ -172,6 +179,3 @@ class GetAllView(BaseView, GetMixin):
172
179
  summary=summary,
173
180
  dependencies=self.get_all_route,
174
181
  )
175
-
176
-
177
-
@@ -14,7 +14,7 @@ from fastgenerateapi.cache.cache_decorator import get_one_cache_decorator
14
14
  from fastgenerateapi.cache.key_builder import generate_key_builder
15
15
  from fastgenerateapi.data_type.data_type import CALLABLE, DEPENDENCIES
16
16
  from fastgenerateapi.schemas_factory import get_one_schema_factory, response_factory
17
- from fastgenerateapi.settings.register_settings import settings
17
+ from fastgenerateapi.settings.all_settings import settings
18
18
  from fastgenerateapi.utils.exception import NOT_FOUND
19
19
 
20
20
 
@@ -16,7 +16,7 @@ from fastgenerateapi.deps import paginator_deps, filter_params_deps
16
16
  from fastgenerateapi.schemas_factory import get_page_schema_factory, response_factory
17
17
  from fastgenerateapi.schemas_factory.get_all_schema_factory import get_list_schema_factory
18
18
  from fastgenerateapi.schemas_factory.get_relation_schema_factory import get_relation_schema_factory
19
- from fastgenerateapi.settings.register_settings import settings
19
+ from fastgenerateapi.settings.all_settings import settings
20
20
 
21
21
 
22
22
  class GetRelationView(BaseView):
@@ -25,7 +25,7 @@ from fastgenerateapi.deps import paginator_deps, filter_params_deps
25
25
  from fastgenerateapi.deps.tree_params_deps import tree_params_deps
26
26
  from fastgenerateapi.schemas_factory import get_one_schema_factory, response_factory
27
27
  from fastgenerateapi.schemas_factory.get_tree_schema_factory import get_tree_schema_factory
28
- from fastgenerateapi.settings.register_settings import settings
28
+ from fastgenerateapi.settings.all_settings import settings
29
29
 
30
30
 
31
31
  class GetTreeView(BaseView):
@@ -10,10 +10,10 @@ from fastgenerateapi.controller.filter_controller import BaseFilter
10
10
  from fastgenerateapi.controller import RouterController
11
11
  from fastgenerateapi.controller.ws_controller import WsController
12
12
 
13
- from fastgenerateapi.settings.register_settings import settings
13
+ from fastgenerateapi.settings.all_settings import settings
14
14
  from starlette.exceptions import HTTPException
15
15
 
16
- from fastgenerateapi.data_type.data_type import DEPENDENCIES, T
16
+ from fastgenerateapi.data_type.data_type import DEPENDENCIES, T, PYDANTIC_SCHEMA
17
17
 
18
18
 
19
19
  class BaseMixin(Generic[T], APIRouter, ABC):
@@ -52,10 +52,13 @@ class BaseMixin(Generic[T], APIRouter, ABC):
52
52
  # if hasattr(self, "_handler_sql_get_all_settings"):
53
53
  # getattr(self, "_handler_sql_get_all_settings")()
54
54
 
55
- def get_base_filter(self, fields: list) -> list:
56
- if fields is None:
57
- return []
58
- return [BaseFilter(field) if not isinstance(field, BaseFilter) else field for field in fields]
55
+ def get_base_filter(self, fields: list, schema: Optional[PYDANTIC_SCHEMA] = None) -> list:
56
+ bast_filter_list = []
57
+ if fields:
58
+ bast_filter_list += [BaseFilter(field) if not isinstance(field, BaseFilter) else field for field in fields]
59
+ if schema:
60
+ bast_filter_list += [BaseFilter((field, model_field.alias)) for field, model_field in schema.__fields__.items()]
61
+ return bast_filter_list
59
62
 
60
63
  @staticmethod
61
64
  def _get_routes(is_controller_field: bool = False) -> List[str]:
@@ -70,7 +73,8 @@ class BaseMixin(Generic[T], APIRouter, ABC):
70
73
  def _get_cls_api_func(cls):
71
74
  func_list = inspect.getmembers(cls, inspect.isfunction)
72
75
 
73
- return [(func[0], inspect.signature(func[1]).return_annotation) for func in func_list if func[0].startswith("view_")]
76
+ return [(func[0], inspect.signature(func[1]).return_annotation) for func in func_list if
77
+ func[0].startswith("view_")]
74
78
 
75
79
  @classmethod
76
80
  def _get_cls_ws_func(cls):
@@ -1,11 +1,19 @@
1
1
  import inspect
2
2
  from typing import Type, Union, List, Optional
3
3
 
4
- from fastgenerateapi.settings.register_settings import settings
4
+ from fastgenerateapi.settings.all_settings import settings
5
5
  from tortoise import Model
6
6
 
7
7
 
8
8
  class DBModelMixin:
9
+ others_description = {
10
+ "gt": "大于",
11
+ "gte": "大于等于",
12
+ "lt": "小于",
13
+ "lte": "小于等于",
14
+ "contains": "模糊搜索",
15
+ "in": "范围",
16
+ }
9
17
 
10
18
  @staticmethod
11
19
  def _get_pk_field(model_class: Type[Model]) -> str:
@@ -16,34 +24,33 @@ class DBModelMixin:
16
24
 
17
25
  @staticmethod
18
26
  def get_field_description(model_class: Type[Model], fields: Union[str, list, tuple, set]) -> str:
19
-
27
+ if fields in ["id", "pk"]:
28
+ return "主键"
20
29
  if type(fields) == str:
21
30
  try:
22
31
  field_info = model_class._meta.fields_map.get(fields)
23
32
  field_info_fk = model_class._meta.fields_map.get(fields.rstrip("_id"))
24
33
  if field_info:
25
- return field_info.description
34
+ return field_info.description or ""
26
35
  elif fields.endswith("_id") and field_info_fk:
27
- return field_info_fk.description
36
+ return field_info_fk.description or ""
28
37
  elif "__" in fields:
29
38
  field_list = fields.split("__", maxsplit=1)
30
39
  description = ""
31
40
  description += DBModelMixin.get_field_description(model_class=model_class, fields=field_list[0])
32
- description += DBModelMixin.get_field_description(
33
- model_class=DBModelMixin._get_foreign_key_relation_class(model_class=model_class, field=field_list[0]),
34
- fields=field_list[1]
35
- )
41
+ if field_list[1] in DBModelMixin.others_description:
42
+ description += DBModelMixin.get_field_description(
43
+ model_class=model_class,
44
+ fields=field_list[1]
45
+ )
46
+ else:
47
+ description += DBModelMixin.get_field_description(
48
+ model_class=DBModelMixin._get_foreign_key_relation_class(model_class=model_class, field=field_list[0]),
49
+ fields=field_list[1]
50
+ )
36
51
  return description
37
52
  else:
38
- others_description = {
39
- "gt": "大于",
40
- "gte": "大于等于",
41
- "lt": "小于",
42
- "lte": "小于等于",
43
- "contains": "模糊搜索",
44
- "in": "范围"
45
- }
46
- return others_description.get(fields, "")
53
+ return DBModelMixin.others_description.get(fields, "")
47
54
 
48
55
  except Exception:
49
56
  return fields
@@ -102,7 +109,10 @@ class DBModelMixin:
102
109
 
103
110
  @staticmethod
104
111
  def _get_foreign_key_relation_class(model_class: Type[Model], field: str) -> Type[Model]:
105
- module = inspect.getmodule(model_class, inspect.getfile(model_class))
106
- res_class = getattr(module, model_class._meta.fields_map.get(field).model_name.split(".")[1])
107
- return res_class
112
+ try:
113
+ module = inspect.getmodule(model_class, inspect.getfile(model_class))
114
+ res_class = getattr(module, model_class._meta.fields_map.get(field).model_name.split(".")[1])
115
+ return res_class
116
+ except:
117
+ return model_class
108
118
 
@@ -1,54 +1,59 @@
1
+ import time
2
+ from io import BytesIO
1
3
  from typing import Union, Optional, Dict, Any
4
+ from urllib.parse import quote
2
5
 
3
6
  from fastapi import HTTPException
4
7
  from fastapi.encoders import jsonable_encoder
5
8
  from pydantic import BaseModel
6
9
 
7
- from fastgenerateapi.settings.register_settings import settings
10
+ from fastgenerateapi.settings.all_settings import settings
8
11
  from starlette.background import BackgroundTask
9
- from starlette.responses import JSONResponse
12
+ from starlette.responses import JSONResponse, Response, StreamingResponse
10
13
 
11
14
  from fastgenerateapi.pydantic_utils.base_model import JSON_ENCODERS
12
15
  from fastgenerateapi.schemas_factory import response_factory
13
16
 
14
17
 
15
- # class CommonResponse(BaseModel):
16
- # success: bool = True
17
- # code: int = 200
18
- # message: str = "请求成功"
19
- # data: Union[dict, str, BaseModel] = {}
20
-
21
-
22
18
  class ResponseMixin:
23
19
 
24
20
  @staticmethod
25
- def success(msg: str = "请求成功",
26
- status_code: int = 200,
27
- code: Optional[int] = None,
28
- data: Union[BaseModel, dict, str, None] = None,
29
- background: Optional[BackgroundTask] = None,
30
- *args,
31
- **kwargs):
21
+ def success(
22
+ msg: str = "请求成功",
23
+ status_code: int = 200,
24
+ code: Optional[int] = None,
25
+ data: Union[BaseModel, dict, str, None] = None,
26
+ background: Optional[BackgroundTask] = None,
27
+ *args,
28
+ **kwargs
29
+ ):
32
30
  if data is None:
33
31
  json_compatible_data = {}
34
32
  else:
35
33
  json_compatible_data = jsonable_encoder(data, custom_encoder=JSON_ENCODERS)
36
34
  if code is None:
37
35
  code = settings.app_settings.CODE_SUCCESS_DEFAULT_VALUE
38
- resp = response_factory()(success=True, code=code, message=msg, data=json_compatible_data)
36
+ resp = response_factory()(**{
37
+ "success": True,
38
+ "code": code,
39
+ settings.app_settings.MESSAGE_RESPONSE_FIELD: msg,
40
+ "data": json_compatible_data
41
+ })
39
42
  kwargs.update(resp.dict())
40
43
  return JSONResponse(kwargs, status_code=status_code, background=background)
41
44
 
42
45
  @staticmethod
43
- def fail(msg: str = "请求失败",
44
- status_code: int = 200,
45
- code: Optional[int] = None,
46
- success: bool = False,
47
- data: Union[BaseModel, dict, str, None] = None,
48
- background: Optional[BackgroundTask] = None,
49
- headers: Optional[Dict[str, Any]] = None,
50
- *args,
51
- **kwargs):
46
+ def fail(
47
+ msg: str = "请求失败",
48
+ status_code: int = 200,
49
+ code: Optional[int] = None,
50
+ # success: bool = False,
51
+ data: Union[BaseModel, dict, str, None] = None,
52
+ background: Optional[BackgroundTask] = None,
53
+ headers: Optional[Dict[str, Any]] = None,
54
+ *args,
55
+ **kwargs,
56
+ ):
52
57
 
53
58
  if data is None:
54
59
  json_compatible_data = {}
@@ -56,7 +61,12 @@ class ResponseMixin:
56
61
  json_compatible_data = jsonable_encoder(data, custom_encoder=JSON_ENCODERS)
57
62
  if code is None:
58
63
  code = settings.app_settings.CODE_FAIL_DEFAULT_VALUE
59
- resp = response_factory()(success=success, code=code, message=msg, data=json_compatible_data)
64
+ resp = response_factory()(**{
65
+ "success": False,
66
+ "code": code,
67
+ settings.app_settings.MESSAGE_RESPONSE_FIELD: msg,
68
+ "data": json_compatible_data
69
+ })
60
70
  kwargs.update(resp.dict())
61
71
  return JSONResponse(
62
72
  kwargs,
@@ -66,11 +76,13 @@ class ResponseMixin:
66
76
  )
67
77
 
68
78
  @staticmethod
69
- def error(msg: str = "系统繁忙,请稍后再试...",
70
- status_code: int = 400,
71
- headers: Optional[Dict[str, Any]] = None,
72
- *args,
73
- **kwargs):
79
+ def error(
80
+ msg: str = "系统繁忙,请稍后再试...",
81
+ status_code: int = 400,
82
+ headers: Optional[Dict[str, Any]] = None,
83
+ *args,
84
+ **kwargs,
85
+ ):
74
86
 
75
87
  raise HTTPException(
76
88
  status_code=status_code,
@@ -78,3 +90,38 @@ class ResponseMixin:
78
90
  headers=headers or {"Access-Control-Allow-Origin": '*'},
79
91
  )
80
92
 
93
+ @staticmethod
94
+ def stream(
95
+ bytes_io: BytesIO,
96
+ file_name: Optional[str] = None,
97
+ media_type: Optional[str] = None,
98
+ is_xlsx: Optional[bool] = None,
99
+ is_docx: Optional[bool] = None,
100
+ is_pdf: Optional[bool] = None,
101
+ ) -> StreamingResponse:
102
+ """
103
+
104
+ :param bytes_io: io.BytesIO()
105
+ :param file_name: 文件名称
106
+ :param media_type: 优先度大于其他参数
107
+ :param is_xlsx: 自动设置media_type
108
+ :param is_docx: 自动设置media_type
109
+ :param is_pdf: 自动设置media_type
110
+ :return: StreamingResponse
111
+ """
112
+
113
+ if not media_type:
114
+ if is_xlsx:
115
+ media_type = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8"
116
+ elif is_docx:
117
+ media_type = "application/vnd.openxmlformats-officedocument.wordprocessingml.document;charset=UTF-8"
118
+ elif is_pdf:
119
+ media_type = "application/pdf"
120
+ headers = {}
121
+ if file_name:
122
+ headers["Content-Disposition"] = f"attachment; filename={quote(file_name, safe='/:?=&')}"
123
+ return StreamingResponse(
124
+ bytes_io,
125
+ media_type= media_type,
126
+ headers=headers,
127
+ )