Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

添加respons_model统一返回 #488

Closed

Conversation

qhp13654398483
Copy link
Contributor

@qhp13654398483 qhp13654398483 commented Jan 15, 2025

@router.funcresponse_model= 字段提供了两个功能
create_detail_response_model :根据 基于SchemaBase 的类提供返回详情的方法
create_paged_response_model: 根据 基于backend/common/pagination._Page 类提供的返回方法
主要作用是在OpenAPI文档中能够针对返回字段解释部分的使用

具体使用举例:

@router.get(
  '/{pk}', 
  summary='获取部门详情', 
  dependencies=[DependsJwtAuth],
  response_model=create_detail_response_model(GetDeptListDetails)
)
async def get_dept(pk: Annotated[int, Path(...)]) -> ResponseModel:
    dept = await dept_service.get(pk=pk)
    data = GetDeptListDetails(**select_as_dict(dept))
    return response_base.success(data=data)

@router.get(
    '',
    summary='(模糊条件)分页获取所有角色',
    dependencies=[
        DependsJwtAuth,
        DependsPagination,
    ],
 response_model=create_detail_response_model(GetDeptListDetails)
)
async def get_pagination_roles(
    db: CurrentSession,
    name: Annotated[str | None, Query()] = None,
    status: Annotated[int | None, Query()] = None,
) -> ResponseModel:
    role_select = await role_service.get_select(name=name, status=status)
    page_data = await paging_data(db, role_select, GetRoleListDetails)
    return response_base.success(data=page_data)

我是这个项目的粉丝,这个项目的使用真的很舒服,让我少写了很多代码,同时我也是通过这个项目让我见识到了fastapi的强大,我也希望能够提供一些有用的贡献

@qhp13654398483 qhp13654398483 marked this pull request as draft January 15, 2025 05:48
@qhp13654398483 qhp13654398483 marked this pull request as ready for review January 15, 2025 05:48
@wu-clan
Copy link
Member

wu-clan commented Jan 15, 2025

非常有趣的实现,我会尽快审查和测试

我的一个直接问题是,示例一中只是存在重复性路由装饰器代码吗

@qhp13654398483
Copy link
Contributor Author

是哒!!!!
顺带一提,我就是为了在OpenAPI 中方便我的前端查看api字段具体信息,其他地方我没有在开发过程中没用到。不过我写的不怎么样,我认为editer大佬你肯定会有其他更好的修改方案

@qhp13654398483
Copy link
Contributor Author

毛躁的我好像写在第一个示例中多写了一丢段脏代码,我删了@router.get(
'/{pk}', 之前的部分

好像删除了 

# 定义分页信息模型
class Pagination(BaseModel):
    total: int = Field(..., description="总条数")
    page: int = Field(..., description="当前页")
    size: int = Field(..., description="每页数量")
    total_pages: int = Field(..., description="总页数")
不影响任何,看来是多余写了这些
@wu-clan
Copy link
Member

wu-clan commented Jan 15, 2025

我们将遵循 fastapi 设计规范进行 opneapi 优化,请给我一点时间,我将重新研究一下它们内部的集成关系,使这个 pr 看起来更好

@qhp13654398483
Copy link
Contributor Author

好滴呢,辛苦大大

@wu-clan
Copy link
Member

wu-clan commented Jan 16, 2025

Hi, @qhp13654398483,非常高兴你提出此宝贵建议,基于当前的已有设计和以下两点,我重新设计了此功能

  1. response_model 和 -> (返回类型) 只需其中一种,无需重复声明
  2. 倾向于使用 -> 而非 response_model 参数

新实现可查看 #490 ,尽管此 PR 不会被合并,但这仍是一个很好的实例

我们在此邀请您加入团队,如果您可接受,请查看官网:关于 -> 加入团队 了解详情

@qhp13654398483
Copy link
Contributor Author

感谢大佬的说明,我发现确实如此两者之间 存在可更替性,我做了一个简单测试,发现确实如此,是我对这里理解不深导致的。不过我测试的时候发现: 以 项目中 (模糊条件)分页获取所有字典 部分为例, 我们使用 -> 和 使用response_model 效果一样,但是当我们 不指向 -> ResponseModel而是指向 ->GetDictDataListDetails 的时候 访问会报错,当我 使用 我提供的 create_paged_response_model 访问时就没问题了。
还有我希望解决的是 这里可以显示问题

  • 原始返回 -> ResponseModel 的页面
image
  • 使用 -> create_paged_response_model(GetDictDataListDetails) 的页面
image
  • 使用 -> GetDictDataListDetails的页面
image

最后我解释一下我的想法: 我希望在localhost:port/docs 当中看到的 每个接口的 Successful Response标签的 Schema 的返回案例是真实的返回请求样式,而不是单纯的ResponseModel。 我的目的并非认为response_model 相反 我认为 -> 更便捷,只是在 OpenAPI上我能看到返回示例我认为更方便
我的最终项目方案是 是用-> create_paged_response_model(DataModel)让我的OpenAPI更好用一些

@wu-clan
Copy link
Member

wu-clan commented Jan 17, 2025

在新的 PR 中实现的效果与此相同,但是返回格式不再是单纯的 ResponseModel,也不是单纯的 Schema,为了统一返回结构,我们并没有采取将所有输出模型集成统一响应结构,而是仅在最终返回时进行处理,这保证了输出模型的灵活性,相关实例可查看 PR 源码或以下实例:

@router.get('/{pk}', summary='获取接口详情', dependencies=[DependsJwtAuth])
async def get_api(pk: Annotated[int, Path(...)]) -> ResponseSchemaModel[GetApiListDetails]:
    api = await api_service.get(pk=pk)
    return response_base.success(data=api)


@router.get(
    '',
    summary='(模糊条件)分页获取所有接口',
    dependencies=[
        DependsJwtAuth,
        DependsPagination,
    ],
)
async def get_pagination_apis(
    request: Request,
    db: CurrentSession,
    name: Annotated[str | None, Query()] = None,
    method: Annotated[str | None, Query()] = None,
    path: Annotated[str | None, Query()] = None,
) -> ResponseSchemaModel[PageData[GetApiListDetails]]:
    api_select = await api_service.get_select(request=request, name=name, method=method, path=path)
    page_data = await paging_data(db, api_select)
    return response_base.success(data=page_data)

@qhp13654398483
Copy link
Contributor Author

nice 感谢你的回答

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants