Skip to content

Commit

Permalink
docs: support convert pydantic model to swagger docs
Browse files Browse the repository at this point in the history
  • Loading branch information
narasux committed Sep 5, 2023
1 parent 5bfa5e5 commit adc7347
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 5 deletions.
1 change: 1 addition & 0 deletions src/bk-user/bkuser/apis/web/data_source/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class DataSourceSearchOutputSLZ(serializers.Serializer):
id = serializers.IntegerField(help_text="数据源 ID")
name = serializers.CharField(help_text="数据源名称")
owner_tenant_id = serializers.CharField(help_text="数据源所属租户 ID")
plugin_id = serializers.CharField(help_text="数据源插件 ID")
plugin_name = serializers.SerializerMethodField(help_text="数据源插件名称")
cooperation_tenants = serializers.SerializerMethodField(help_text="协作公司")
status = serializers.CharField(help_text="数据源状态")
Expand Down
16 changes: 13 additions & 3 deletions src/bk-user/bkuser/apis/web/data_source/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
from bkuser.apis.web.mixins import CurrentUserTenantMixin
from bkuser.apps.data_source.constants import DataSourceStatus
from bkuser.apps.data_source.models import DataSource, DataSourcePlugin
from bkuser.apps.data_source.plugins.constants import DATA_SOURCE_PLUGIN_CONFIG_SCHEMA_MAP
from bkuser.apps.data_source.signals import post_create_data_source, post_update_data_source
from bkuser.common.error_codes import error_codes
from bkuser.common.views import ExcludePatchAPIViewMixin, ExcludePutAPIViewMixin
Expand Down Expand Up @@ -77,7 +78,10 @@ def get(self, request, *args, **kwargs):
tags=["data_source"],
operation_description="新建数据源",
request_body=DataSourceCreateInputSLZ(),
responses={status.HTTP_201_CREATED: DataSourceCreateOutputSLZ()},
responses={
status.HTTP_201_CREATED: DataSourceCreateOutputSLZ(),
**DATA_SOURCE_PLUGIN_CONFIG_SCHEMA_MAP,
},
)
def post(self, request, *args, **kwargs):
slz = DataSourceCreateInputSLZ(data=request.data)
Expand Down Expand Up @@ -115,7 +119,10 @@ def get_queryset(self):
@swagger_auto_schema(
tags=["data_source"],
operation_description="数据源详情",
responses={status.HTTP_200_OK: DataSourceRetrieveOutputSLZ()},
responses={
status.HTTP_200_OK: DataSourceRetrieveOutputSLZ(),
**DATA_SOURCE_PLUGIN_CONFIG_SCHEMA_MAP,
},
)
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
Expand All @@ -124,7 +131,10 @@ def get(self, request, *args, **kwargs):
tags=["data_source"],
operation_description="更新数据源",
request_body=DataSourceUpdateInputSLZ(),
responses={status.HTTP_204_NO_CONTENT: ""},
responses={
status.HTTP_204_NO_CONTENT: "",
**DATA_SOURCE_PLUGIN_CONFIG_SCHEMA_MAP,
},
)
def put(self, request, *args, **kwargs):
data_source = self.get_object()
Expand Down
7 changes: 7 additions & 0 deletions src/bk-user/bkuser/apps/data_source/plugins/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,15 @@

from bkuser.apps.data_source.constants import DataSourcePluginEnum
from bkuser.apps.data_source.plugins.local.models import LocalDataSourcePluginConfig
from bkuser.utils.pydantic import gen_openapi_schema

# 数据源插件配置类映射表
DATA_SOURCE_PLUGIN_CONFIG_CLASS_MAP = {
DataSourcePluginEnum.LOCAL: LocalDataSourcePluginConfig,
}

# 数据源插件配置类 JsonSchema 映射表
DATA_SOURCE_PLUGIN_CONFIG_SCHEMA_MAP = {
f"plugin_config:{plugin_id}": gen_openapi_schema(model)
for plugin_id, model in DATA_SOURCE_PLUGIN_CONFIG_CLASS_MAP.items()
}
17 changes: 16 additions & 1 deletion src/bk-user/bkuser/utils/pydantic.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.
"""
from pydantic import ValidationError
import json
from typing import Type

import jsonref
from drf_yasg import openapi
from pydantic import BaseModel, ValidationError


def stringify_pydantic_error(exc: ValidationError) -> str:
Expand All @@ -26,3 +31,13 @@ def stringify_pydantic_error(exc: ValidationError) -> str:
err_msgs.append(msg)

return ", ".join(err_msgs)


def gen_openapi_schema(model: Type[BaseModel]) -> openapi.Schema:
"""Convert pydantic model as drf_yasg openapi schema (without any jsonRef)"""
# Q: why need json dumps and jsonref.loads?
# A: according to https://github.com/pydantic/pydantic/issues/889
# pydantic generate json schema with jsonRef,
# which is not compatible with drf_yasg.openapi.schema
json_schema = jsonref.loads(json.dumps(model.model_json_schema()))
return openapi.Schema(**json_schema)
18 changes: 17 additions & 1 deletion src/bk-user/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/bk-user/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ django-redis = "5.3.0"
pydantic = "2.1.1"
zxcvbn = "4.4.28"
phonenumbers = "8.13.18"
jsonref = "1.1.0"

[tool.poetry.group.dev.dependencies]
ruff = "^0.0.277"
Expand Down

0 comments on commit adc7347

Please sign in to comment.