fastgenerateapi 1.1.19__tar.gz → 1.2.1__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 (116) hide show
  1. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/PKG-INFO +2 -12
  2. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/README.md +1 -11
  3. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/__init__.py +1 -1
  4. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/__version__.py +1 -1
  5. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/api_view/base_view.py +51 -13
  6. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/api_view/create_view.py +41 -26
  7. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/api_view/delete_filter_view.py +15 -5
  8. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/api_view/delete_tree_view.py +13 -5
  9. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/api_view/delete_view.py +13 -5
  10. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/api_view/get_all_view.py +21 -13
  11. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/api_view/get_one_view.py +11 -13
  12. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/api_view/get_relation_view.py +8 -3
  13. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/api_view/get_tree_view.py +8 -3
  14. fastgenerateapi-1.2.1/fastgenerateapi/api_view/mixin/save_mixin.py +16 -0
  15. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/api_view/switch_view.py +5 -13
  16. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/api_view/update_relation_view.py +9 -2
  17. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/api_view/update_view.py +39 -22
  18. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/schemas_factory/common_function.py +7 -1
  19. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/schemas_factory/common_schema_factory.py +1 -1
  20. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/schemas_factory/create_schema_factory.py +44 -2
  21. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/schemas_factory/get_all_schema_factory.py +74 -28
  22. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/schemas_factory/get_one_schema_factory.py +39 -0
  23. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/schemas_factory/update_schema_factory.py +44 -2
  24. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/settings/__init__.py +0 -1
  25. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/settings/all_settings.py +44 -23
  26. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/settings/app_settings.py +3 -0
  27. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/settings/db_settings.py +1 -1
  28. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/settings/etcd_settings.py +9 -1
  29. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi.egg-info/PKG-INFO +2 -12
  30. fastgenerateapi-1.1.19/fastgenerateapi/api_view/mixin/save_mixin.py +0 -14
  31. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/LICENSE +0 -0
  32. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/api_view/__init__.py +0 -0
  33. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/api_view/api_view.py +0 -0
  34. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/api_view/mixin/__init__.py +0 -0
  35. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/api_view/mixin/base_mixin.py +0 -0
  36. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/api_view/mixin/dbmodel_mixin.py +0 -0
  37. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/api_view/mixin/get_mixin.py +0 -0
  38. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/api_view/mixin/response_mixin.py +0 -0
  39. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/api_view/mixin/tool_mixin.py +0 -0
  40. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/api_view/mixin/utils/__init__.py +0 -0
  41. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/api_view/mixin/utils/docx_util.py +0 -0
  42. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/api_view/mixin/utils/file_util.py +0 -0
  43. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/api_view/mixin/utils/pdf_util.py +0 -0
  44. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/api_view/mixin/utils/xlsx_util.py +0 -0
  45. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/api_view/mixin/utils/zip_util.py +0 -0
  46. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/api_view/sql_get_view.py +0 -0
  47. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/cache/__init__.py +0 -0
  48. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/cache/cache_decorator.py +0 -0
  49. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/cache/key_builder.py +0 -0
  50. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/channel/__init__.py +0 -0
  51. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/channel/connection_manager.py +0 -0
  52. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/channel/consumer.py +0 -0
  53. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/channel/websocket_view.py +0 -0
  54. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/controller/__init__.py +0 -0
  55. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/controller/filter_controller.py +0 -0
  56. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/controller/router_controller.py +0 -0
  57. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/controller/rpc_controller.py +0 -0
  58. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/controller/search_controller.py +0 -0
  59. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/controller/ws_controller.py +0 -0
  60. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/data_type/__init__.py +0 -0
  61. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/data_type/data_type.py +0 -0
  62. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/data_type/mysql_data_type.py +0 -0
  63. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/deps/__init__.py +0 -0
  64. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/deps/filter_params_deps.py +0 -0
  65. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/deps/paginator_deps.py +0 -0
  66. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/deps/tree_params_deps.py +0 -0
  67. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/example/__init__.py +0 -0
  68. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/example/models.py +0 -0
  69. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/example/routers.py +0 -0
  70. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/example/schemas.py +0 -0
  71. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/example/views.py +0 -0
  72. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/fastapi_utils/__init__.py +0 -0
  73. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/fastapi_utils/all.py +0 -0
  74. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/fastapi_utils/param_utils.py +0 -0
  75. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/fastapi_utils/response_utils.py +0 -0
  76. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/model/__init__.py +0 -0
  77. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/model/base_model.py +0 -0
  78. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/my_fields/__init__.py +0 -0
  79. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/my_fields/aes_field.py +0 -0
  80. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/my_fields/enum_field.py +0 -0
  81. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/my_fields/pk_field.py +0 -0
  82. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/my_fields/pwd_field.py +0 -0
  83. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/my_fields/soft_delete_field.py +0 -0
  84. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/my_fields/validator.py +0 -0
  85. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/pydantic_utils/__init__.py +0 -0
  86. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/pydantic_utils/base_model.py +0 -0
  87. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/pydantic_utils/base_settings.py +0 -0
  88. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/pydantic_utils/json_encoders.py +0 -0
  89. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/schemas_factory/__init__.py +0 -0
  90. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/schemas_factory/filter_schema_factory.py +0 -0
  91. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/schemas_factory/get_relation_schema_factory.py +0 -0
  92. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/schemas_factory/get_tree_schema_factory.py +0 -0
  93. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/schemas_factory/response_factory.py +0 -0
  94. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/schemas_factory/sql_get_all_schema_factory.py +0 -0
  95. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/settings/file_settings.py +0 -0
  96. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/settings/jwt_settings.py +0 -0
  97. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/settings/otlp_settings.py +0 -0
  98. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/settings/redis_settings.py +0 -0
  99. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/settings/sms_settings.py +0 -0
  100. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/settings/system_settings.py +0 -0
  101. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/utils/__init__.py +0 -0
  102. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/utils/aes.py +0 -0
  103. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/utils/auto_discover.py +0 -0
  104. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/utils/exception.py +0 -0
  105. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/utils/file_utils.py +0 -0
  106. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/utils/pwd_utils.py +0 -0
  107. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/utils/ramdom_utils.py +0 -0
  108. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/utils/snowflake.py +0 -0
  109. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/utils/str_util.py +0 -0
  110. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi/utils/swagger_to_js.py +0 -0
  111. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi.egg-info/SOURCES.txt +0 -0
  112. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi.egg-info/dependency_links.txt +0 -0
  113. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/fastgenerateapi.egg-info/top_level.txt +0 -0
  114. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/script/__init__.py +0 -0
  115. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/setup.cfg +0 -0
  116. {fastgenerateapi-1.1.19 → fastgenerateapi-1.2.1}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fastgenerateapi
3
- Version: 1.1.19
3
+ Version: 1.2.1
4
4
  Summary: FastAPIView Class View
5
5
  Author: ShiLiang
6
6
  Author-email: 2509144896@qq.com
@@ -25,7 +25,7 @@ License-File: LICENSE
25
25
 
26
26
  #### 版本说明
27
27
  [pydantic-v2]
28
- 稳定版本:v1.1.15+
28
+ 稳定版本:v1.1.29+
29
29
  建议python版本:3.9+
30
30
  推荐fastapi版本:0.103.2+
31
31
  推荐pydantic版本:2.11.5+
@@ -107,16 +107,6 @@ class XxxView(APIView):
107
107
  model_class = XxxModel
108
108
  ```
109
109
 
110
- #### 继承 APIView 使用,关闭其中部分路由示例
111
- ```python
112
- from core.crud.api_view import APIView
113
-
114
- class XxxView(APIView):
115
- create_route = False
116
- get_one_route = False
117
- update_route = False
118
- delete_route = False
119
- ```
120
110
  #### 查询/创建/修改字段限制及校验示例
121
111
  - 如果有唯一字段或者联合唯一字段自动校验是否为唯一值
122
112
  ```python
@@ -7,7 +7,7 @@
7
7
 
8
8
  #### 版本说明
9
9
  [pydantic-v2]
10
- 稳定版本:v1.1.15+
10
+ 稳定版本:v1.1.29+
11
11
  建议python版本:3.9+
12
12
  推荐fastapi版本:0.103.2+
13
13
  推荐pydantic版本:2.11.5+
@@ -89,16 +89,6 @@ class XxxView(APIView):
89
89
  model_class = XxxModel
90
90
  ```
91
91
 
92
- #### 继承 APIView 使用,关闭其中部分路由示例
93
- ```python
94
- from core.crud.api_view import APIView
95
-
96
- class XxxView(APIView):
97
- create_route = False
98
- get_one_route = False
99
- update_route = False
100
- delete_route = False
101
- ```
102
92
  #### 查询/创建/修改字段限制及校验示例
103
93
  - 如果有唯一字段或者联合唯一字段自动校验是否为唯一值
104
94
  ```python
@@ -7,7 +7,7 @@
7
7
  # .88
8
8
  # d8888P
9
9
 
10
-
10
+ author="石亮"
11
11
  from fastgenerateapi.api_view.api_view import APIView, CreateView, GetOneView, GetAllView, UpdateView, DeleteView, \
12
12
  SwitchView
13
13
  from fastgenerateapi.api_view.get_tree_view import GetTreeView
@@ -8,7 +8,7 @@
8
8
  # d8888P
9
9
 
10
10
 
11
- VERSION = (1, 1, 19)
11
+ VERSION = (1, 2, 1)
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,8 @@ 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
+ is_with_prefetch: Optional[bool] = False
29
+ schema: Optional[Type[BaseModel]] = None # 返回序列化[未使用]
28
30
  dependencies: Optional[Sequence[params.Depends]] = None
29
31
  tags: Optional[List[str]] = None # swagger标签
30
32
  router_args: Dict[str, any] = None
@@ -35,6 +37,7 @@ class BaseView(BaseMixin, ResponseMixin, ToolMixin, DBModelMixin):
35
37
  "avatar": None, # 外键内容对应字典的形式
36
38
  "avatar": ["id", ("url", "avatar_url")] # 增加 avatar_id,avatar_url2个字段
37
39
  }
40
+ is_with_prefetch: 是否带有列表的prefetch_related_fields
38
41
 
39
42
  # router_args: List[Union[str, tuple, BaseRouterSummary]] = None
40
43
  # 给函数设置路由以及其他参数
@@ -157,36 +160,46 @@ class BaseView(BaseMixin, ResponseMixin, ToolMixin, DBModelMixin):
157
160
  @classmethod
158
161
  async def check_unique_field(
159
162
  cls,
160
- request_data: Union[BaseModel, Model], # 创建或修改的参数数据
161
- model_class: Type[Model], # 数据库模型
163
+ data_dict: dict,
164
+ model_class: Type[Model],
162
165
  model: Union[Model, None] = None
163
166
  ):
164
- check_unique_fields = cls._get_unique_fields(model_class) + cls._get_foreign_key_fields(model_class)
167
+ """
168
+ 校验模型中设置了 唯一索引和联合唯一索引 的字段
169
+ :param data_dict: 修改或创建的数据字典
170
+ :param model_class: 数据库模型
171
+ :param model: 修改前的数据,用于判断是否修改了字段,当唯一字段与数据data_dict一致时,不会做校验
172
+ :return:
173
+ """
174
+ check_unique_fields = cls._get_unique_fields(model_class)
165
175
  check_unique_together_fields = cls._get_unique_together_fields(model_class)
166
176
  for unique_field in check_unique_fields:
167
- if hasattr(request_data, unique_field):
168
- if model and getattr(request_data, unique_field) == getattr(model, unique_field):
177
+ if unique_field in data_dict:
178
+ unique_field_value = data_dict.get(unique_field)
179
+ if model and unique_field_value == getattr(model, unique_field):
169
180
  continue
170
- if await model_class.filter(**{unique_field: getattr(request_data, unique_field)}).first():
171
- return cls.error(msg=f"{cls.get_field_description(model_class, unique_field)}已存在相同值:{getattr(request_data, unique_field)}")
181
+ if await model_class.filter(**{unique_field: unique_field_value}).first():
182
+ return cls.error(msg=f"{cls.get_field_description(model_class, unique_field)}已存在相同值:{unique_field_value}")
172
183
  for unique_together_fields in check_unique_together_fields:
173
184
  filter_fields = {}
174
185
  is_equal = True
175
186
  description_fields = []
176
187
  for unique_together_field in unique_together_fields:
188
+ has_unique_together_field = unique_together_field in data_dict
189
+ unique_together_field_value = data_dict.get(unique_together_field)
177
190
  if model:
178
- if hasattr(request_data, unique_together_field):
179
- filter_fields[unique_together_field] = getattr(request_data, unique_together_field)
180
- if getattr(request_data, unique_together_field, None) != getattr(model, unique_together_field):
191
+ if has_unique_together_field:
192
+ filter_fields[unique_together_field] = unique_together_field_value
193
+ if unique_together_field_value != getattr(model, unique_together_field):
181
194
  is_equal = False
182
195
  description_fields.append(unique_together_field)
183
196
  else:
184
197
  filter_fields[unique_together_field] = getattr(model, unique_together_field)
185
198
  else:
186
- if hasattr(request_data, unique_together_field):
199
+ if has_unique_together_field:
187
200
  is_equal = False
188
201
  description_fields.append(unique_together_field)
189
- filter_fields[unique_together_field] = getattr(request_data, unique_together_field)
202
+ filter_fields[unique_together_field] = unique_together_field_value
190
203
  if is_equal:
191
204
  continue
192
205
 
@@ -225,5 +238,30 @@ class BaseView(BaseMixin, ResponseMixin, ToolMixin, DBModelMixin):
225
238
  result[key] = val[0]
226
239
  return result
227
240
 
241
+ def gen_get_one_response_schema(self):
242
+ if not hasattr(self, "get_one_schema") or not self.get_one_schema:
243
+ get_one_schema_include = []
244
+ if hasattr(self, "is_with_prefetch") and self.is_with_prefetch and self.prefetch_related_fields:
245
+ for key, value in self.prefetch_related_fields.items():
246
+ if value and type(value) in [list, tuple, set]:
247
+ for val in value:
248
+ val_str = val
249
+ if type(val) in [list, tuple, set]:
250
+ val_str = val[0]
251
+ get_one_schema_include.append(key + "__" + val_str)
252
+ self.get_one_schema = get_one_schema_factory(model_class=self.model_class, include=get_one_schema_include)
253
+
254
+ return self.get_one_schema
255
+
256
+ def gen_get_one_response_schema_factory(self):
257
+ """
258
+ 如果get_one_response_schema不存在,则生成
259
+ :return:
260
+ """
261
+ self.gen_get_one_response_schema()
262
+ self.get_one_response_schema_factory = response_factory(self.get_one_schema, name="GetOne")
263
+
264
+ return self.get_one_response_schema_factory
265
+
228
266
 
229
267
 
@@ -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,58 +19,67 @@ 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()
34
37
  async def create(self, request_data, *args, **kwargs):
35
38
  try:
36
- model = await self.set_create_fields(request_data=request_data, *args, **kwargs)
39
+ data_dict = await self.set_create_fields(request_data=request_data, *args, **kwargs)
40
+ data_dict = await self.set_save_fields(data_dict, request_data=request_data, *args, **kwargs)
41
+ model = await self.set_create_model(data_dict, request_data=request_data, *args, **kwargs)
37
42
  except ValueError as e:
38
43
  error_field = str(e).split(" ")[0]
39
44
  if getattr(request_data, error_field):
40
45
  return self.error(msg=f"{self.get_field_description(self.model_class, error_field)}格式不正确")
41
46
  return self.error(msg=f"{self.get_field_description(self.model_class, error_field)}不能为空")
42
47
 
43
- model = await self.set_save_model(model=model, request_data=request_data, *args, **kwargs)
44
-
45
- model = await self.set_create_model(model=model, request_data=request_data, *args, **kwargs)
46
-
47
- await self.check_unique_field(model, model_class=self.model_class)
48
-
48
+ await self.check_unique_field(data_dict, model_class=self.model_class)
49
49
  await model.save()
50
50
 
51
- model = await self.model_class.filter(id=model.id).prefetch_related(
52
- *self.prefetch_related_fields.keys()).first()
53
-
54
- await self.setattr_model(model, prefetch_related_fields=self.prefetch_related_fields)
51
+ if settings.app_settings.WHETHER_CREATE_RESPONSE_DATA:
52
+ if self.is_with_prefetch:
53
+ model = await self.get_object(model.id, self.model_class, self.is_with_prefetch)
54
+ await self.setattr_model(model, prefetch_related_fields=self.prefetch_related_fields)
55
55
 
56
- # await self.setattr_model_rpc(self.rpc_class, model, self.rpc_param)
56
+ return self.create_response_schema.model_validate(model)
57
57
 
58
- return self.get_one_schema.from_orm(model)
58
+ return
59
59
 
60
- async def set_create_fields(self, request_data, *args, **kwargs):
60
+ async def set_create_fields(self, request_data, *args, **kwargs) -> dict:
61
61
  """
62
- 添加属性: request_data.user_id = request.user.id
62
+ 添加属性:
63
+ data_dict = request_data.dict(exclude_unset=True)
64
+ data_dict.update({
65
+ "user_id": request.user.id,
66
+ })
67
+ return data_dict
63
68
  """
64
69
 
65
- return self.model_class(**request_data.dict(exclude_unset=True))
70
+ return request_data.dict(exclude_unset=True)
66
71
 
67
- async def set_create_model(self, model: Model, request_data, *args, **kwargs) -> Model:
72
+ async def set_create_model(self, data_dict: dict, request_data, *args, **kwargs) -> Model:
68
73
  """
69
- 添加属性: model.user_id = request.user.id
74
+ 在数据模型校验前后修改值
75
+ - 可用于全局修改
76
+ 添加属性:
77
+ data_dict.update({
78
+ "user_id": request.user.id,
79
+ })
70
80
  """
71
81
 
72
- return model
82
+ return self.model_class(**data_dict)
73
83
 
74
84
  def _create_decorator(self, *args: Any, **kwargs: Any) -> DecoratedCallable:
75
85
  async def route(
@@ -91,10 +101,15 @@ class CreateView(BaseView, SaveMixin):
91
101
  if not self.create_route:
92
102
  return
93
103
  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")
104
+
105
+ func_type = inspect.signature(self.create).return_annotation
106
+ if func_type != inspect._empty and func_type is not None:
107
+ self.create_response_schema = func_type
108
+ if self.create_response_schema:
109
+ self.create_response_schema_factory = response_factory(self.create_response_schema, name="Create")
110
+ else:
111
+ self.create_response_schema_factory = self.gen_get_one_response_schema_factory()
112
+
98
113
  doc = self.create.__doc__
99
114
  summary = doc.strip().split("\n")[0] if doc else f"Create"
100
115
  path = f"/{settings.app_settings.ROUTER_CREATE_SUFFIX_FIELD}" if settings.app_settings.ROUTER_WHETHER_ADD_SUFFIX else ""
@@ -102,7 +117,7 @@ class CreateView(BaseView, SaveMixin):
102
117
  path=path,
103
118
  endpoint=self._create_decorator(),
104
119
  methods=["POST"],
105
- response_model=self.get_one_response_schema, # type: ignore
120
+ response_model=self.create_response_schema_factory, # type: ignore
106
121
  summary=summary,
107
122
  dependencies=self.create_route,
108
123
  )
@@ -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,18 +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
- get_all_schema_include.append(key + "__" + val)
178
- self.get_all_schema = self.get_all_schema or get_all_schema_factory(
179
- self.model_class, include=get_all_schema_include
180
- ) 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()
181
189
  self.get_page_schema = get_page_schema_factory(self.get_all_schema)
182
190
  self.get_list_schema = get_list_schema_factory(self.get_all_schema)
183
- 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")
184
192
  doc = self.get_all.__doc__
185
193
  summary = doc.strip().split("\n")[0] if doc else "Get All"
186
194
  path = f"/{settings.app_settings.ROUTER_GET_ALL_SUFFIX_FIELD}" if settings.app_settings.ROUTER_WHETHER_ADD_SUFFIX else ""
@@ -188,7 +196,7 @@ class GetAllView(BaseView, GetMixin):
188
196
  path=path,
189
197
  endpoint=self._get_all_decorator(),
190
198
  methods=["GET"],
191
- response_model=self.get_all_response_schema,
199
+ response_model=self.get_all_response_schema_factory,
192
200
  summary=summary,
193
201
  dependencies=self.get_all_route,
194
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
@@ -24,7 +25,6 @@ class GetOneView(BaseView, GetMixin):
24
25
 
25
26
  get_one_route: Union[bool, DEPENDENCIES] = True
26
27
  get_one_schema: Optional[Type[BaseModel]] = None
27
- is_with_prefetch: Optional[bool] = False
28
28
  """
29
29
  get_one_route: 获取详情路由开关,可以放依赖函数列表
30
30
  get_one_schema: 返回序列化
@@ -34,6 +34,8 @@ class GetOneView(BaseView, GetMixin):
34
34
  - 优选模型层get_one_include和get_one_exclude(同时存在交集)
35
35
  - 合并模型层include和exclude(同时存在交集)
36
36
  - 模型层所有字段
37
+
38
+ prefetch_related_fields:额外展示字段
37
39
  is_with_prefetch: 是否带有列表的prefetch_related_fields
38
40
  """
39
41
 
@@ -66,17 +68,13 @@ class GetOneView(BaseView, GetMixin):
66
68
  def _handler_get_one_settings(self):
67
69
  if not self.get_one_route:
68
70
  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
- get_one_schema_include.append(key + "__" + val)
75
- self.get_one_schema = self.schema or self.get_one_schema or get_one_schema_factory(
76
- model_class=self.model_class,
77
- include=get_one_schema_include,
78
- )
79
- self.get_one_response_schema = response_factory(self.get_one_schema, name="GetOne")
71
+
72
+ func_type = inspect.signature(self.get_one).return_annotation
73
+ if func_type != inspect._empty and func_type is not None:
74
+ self.get_one_schema = func_type
75
+ if not self.get_one_schema:
76
+ self.get_one_schema = self.gen_get_one_response_schema()
77
+ self.get_one_response_schema_factory = response_factory(self.get_one_schema, name="GetOne")
80
78
  doc = self.get_one.__doc__
81
79
  summary = doc.strip().split("\n")[0] if self.get_one.__doc__ else "Get One"
82
80
  path = f"/{settings.app_settings.ROUTER_GET_ONE_SUFFIX_FIELD}/{'{pk}'}" if settings.app_settings.ROUTER_WHETHER_ADD_SUFFIX else "/{pk}"
@@ -84,7 +82,7 @@ class GetOneView(BaseView, GetMixin):
84
82
  path=path,
85
83
  endpoint=self._get_one_decorator(),
86
84
  methods=["GET"],
87
- response_model=self.get_one_response_schema,
85
+ response_model=self.get_one_response_schema_factory,
88
86
  summary=summary,
89
87
  dependencies=self.get_one_route,
90
88
  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
  )