首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

基于SqlAlchemy+Pydantic+FastApi的Python开发框架的路由处理

编程知识
2024年09月26日 12:33

在前面随笔《基于SqlAlchemy+Pydantic+FastApi的Python开发框架 》中介绍了框架总体的内容,其中主要的理念就是通过抽象接口的方式,实现代码的重用,提高开发效率。本篇随笔深入介绍一下FastApi的路由处理部分的内容,通过基类继承的方式,我们可以简化路由器(或者叫Web API 控制器)的基础接口函数的编写,直接重用基类即可。对于子类的一些特殊的重写操作,或者增加自定义的路由接口,也分别介绍如何处理。

1、开发框架的路由处理基类

我在前面介绍了,对于Python中的FastAPI路由对象类,我们也做了抽象的处理,关系如下所示。

绿色部分的BaseController为基类控制器(或基类路由类),黄色部分为我们实际业务的类,也就是子类路由对象。

基类路由类的定义如下所示,通过接受一些泛型参数,实现之类的个性化特性处理。

class BaseController(Generic[ModelType, PrimaryKeyType, PageDtoType, DtoType]):
    """
    基类控制器,定义通用的接口和路由
    """

    def __init__(
        self,
        crud: BaseCrud[ModelType, PrimaryKeyType, PageDtoType, DtoType],
        pagedto_class: Type[PageDtoType],
        dto_class: Type[DtoType],
        router: APIRouter,
    ):
        self.crud = crud
        self.router = router
        self.dto_class = dto_class  # 用于转换ORM对象为Pydantic对象
        self.pagedto_class = pagedto_class  # 用于转换请求参数为PageDto对象

由于路由实例也是从外部传入,因此最终我们使用的是一个总的路由实例对象

最终我们在一个总的Api路由类(api.py)中汇总所有的路由信息,如下所示。

api_router = APIRouter()

api_router.include_router(customer.router, prefix="/api/customer", tags=["Customer"])
api_router.include_router(product.router, prefix="/api/product", tags=["Product"])

api_router.include_router(dicttype.router, prefix="/api/dicttype", tags=["DictType"])
api_router.include_router(dictdata.router, prefix="/api/dictdata", tags=["DictData"])

api_router.include_router(user.router, prefix="/api/user", tags=["User"])
api_router.include_router(ou.router, prefix="/api/ou", tags=["OU"])
api_router.include_router(role.router, prefix="/api/role", tags=["Role"])

.....

最后,我们在FastApi入口中注册并接入它们即可

# 添加api总的路由
from api.v1.api import api_router

 # API
def register_app():
    # FastAPI
    app = FastAPI(
        title=settings.APP_NAME,
        version=settings.APP_VERSION,
        summary=settings.APP_NAME,
        description=settings.DESCRIPTION,
        # docs_url=settings.DOCS_URL,
        # redoc_url=settings.REDOCS_URL,
        # openapi_url=settings.OPENAPI_URL,
        # default_response_class=AjaxResponse,
        lifespan=register_init,
    )
    app.include_router(api_router)

这样所有的路由信息全部汇总,就可以出现在fastApi的Swagger文档界面中了。

 

2、子类路由对基类函数的重写和增加新接口

前面小节介绍了总体路由的接入处理,以及一些默认具有的API接口,但是我们这里还没有介绍它们之间的继承信息。

对于单个业务对象来说,例如对于客户信息的对象,它默认就具有所有的基类API接口。

它们的关系是如何的,如何做到默认继承基类的相关接口的呢?

## app\api\v1\endpoints\customer.py

# 创建路由,用于处理自定义接口
router = APIRouter()

# 使用基类控制器,可以继承常规CRUD的接口,并自动生成路由,依赖注入,数据库连接等功能 ——构建方式2
controller = BaseController[Customer, str, CustomerPageDto, CustomerDto](
    customer_crud,
    pagedto_class=CustomerPageDto,
    dto_class=CustomerDto,
    router=router,
)
controller.init_router()  # 初始化常规CRUD等接口的路由

上面就是对应Customer表的API控制器(路由类)的定义,这个主要就是直接使用基类构造一个对象,并使用该对象的基类函数进行初始化路由地址(默认具有的所有基类API接口)。

如果我们还需要增加一些特殊的API接口,那么我们在router 对象创建后,直接使用它进行增加即可,如下所示

@router.get(
    "/by-name",
    response_model=AjaxResponse[CustomerDto | None],
    summary="根据名称获取记录",
    dependencies=[DependsJwtAuth],
)
async def get_by_name(
    name: Annotated[str | None, Query()],
    request: Request,
    db: AsyncSession = Depends(get_db),
):
    item = await customer_crud.get_by_name(db, name)
    item = CustomerDto.model_validate(item)
    return AjaxResponse(item)

这样在运行FastAPI应用后,就可以看到Swagger的文档中增加了对应的接口信息了,如下所示。

 如果我们要重写一些控制器基类定义的get的处理方法,如对于用户信息的Get方法,我们除了获得对应的用户信息外,还需要增加一些额外的机构、角色的信息给记录,那么我们可以继承基类并重写Get方法来实现,如下是重写控制器基类的处理代码。

##app\api\v1\endpoints\user.py

# 继承基类,并重写基类某些函数 ——构建方式1
class UserController(BaseController[User, int, UserPageDto, GetCurrentUserInfoDetail]):
    def __init__(self):
        super().__init__(
            user_crud,
            pagedto_class=UserPageDto,
            dto_class=UserDto,
            router=router,
        )

    # 重写基类函数,增加自定义接口处理
    async def get(cls, id: int, db: AsyncSession = Depends(get_db)):
        item = await user_crud.get(db, id)
        if not item:
            raise ItemNotFoundException()

        dto = GetCurrentUserInfoDetail.model_validate(item)

        # 增加角色名称列表
        roles = await role_crud.get_roles_by_user(db, id)
        dto.rolenames = [role.name for role in roles]  # 增加角色名称列表

        # 增加机构名称列表
        ous = await ou_crud.get_ous_by_user(db, id)
        dto.ounames = [ou.name for ou in ous]  # 增加机构名称列表

        dto.issuperadmin = (
            dto.rolenames.count("超级管理员") > 0
        )  # 增加是否超级管理员字段
        dto.isadmin = (
            dto.issuperadmin or dto.rolenames.count("管理员") > 0
        )  # 增加是否管理员字段
        return AjaxResponse(dto)

controller = UserController()

controller.init_router()  # 初始化常规CRUD等接口的路由

所以,综上的处理方式,我们看到,如果是增加一些接口,我们可以直接用基类控制器的实例对象来处理即可(简单),如果需要重写某些基类的接口处理函数,那么我们继承基类构建之类,并提供重写函数,然后实例化子类对象,初始化路由处理即可。

然后通过在总的路由处理Python类中统一引入即可。

##app\api\v1\api.py
from fastapi import APIRouter
from api.v1.endpoints import (customer, product,dicttype, dictdata, tablenumber, systemparams,  systemparamsdir,)
from api.v1.endpoints import ( login,user,ou,role, loginlog, operationlog, systemtype, blackip, function, menu, roledata,  fieldpermit, fielddomain)
************** api_router
= APIRouter() api_router.include_router(customer.router, prefix="/api/customer", tags=["Customer"]) api_router.include_router(product.router, prefix="/api/product", tags=["Product"]) api_router.include_router(dicttype.router, prefix="/api/dicttype", tags=["DictType"]) api_router.include_router(dictdata.router, prefix="/api/dictdata", tags=["DictData"]) api_router.include_router(user.router, prefix="/api/user", tags=["User"]) api_router.include_router(ou.router, prefix="/api/ou", tags=["OU"]) api_router.include_router(role.router, prefix="/api/role", tags=["Role"]) ..............

然后我们在Main函数中抽离相关的处理路逻辑。

import uvicorn
from pathlib import Pathfrom core.config import settings
from core.register_app import register_app

app = register_app()if __name__ == "__main__":
    try:
        config = uvicorn.Config(
            app=f"{Path(__file__).stem}:app",
            reload=True,
            host=settings.SERVER_IP,
            port=settings.SERVER_PORT,
            log_config="app/uvicorn_config.json",  # 日志配置
        )
        server = uvicorn.Server(config)
        server.run()
    except Exception as e:
        raise e

在 register_app 函数中统一处理所有相关的逻辑即可,这样可以简化入口的处理复杂度。

##app\core\register_app.py 
def
register_app(): # FastAPI app = FastAPI( title=settings.APP_NAME, version=settings.APP_VERSION, summary=settings.APP_NAME, description=settings.DESCRIPTION, lifespan=register_init, ) # 日志 register_logger() # 静态文件 register_static_file(app) # 中间件 register_middleware(app) # 路由 register_router(app) # 全局异常处理 register_exception(app) return app

 

From:https://www.cnblogs.com/wuhuacong/p/18433258
本文地址: http://www.shuzixingkong.net/article/2318
0评论
提交 加载更多评论
其他文章 作为博主和曾经员工,谈谈近期的园子
最近,有很多朋友微信我,说博客园最近在求救,你怎么看? 怎么看?不怎么看,微笑而过。 其实救园我很久之前就关注到了,很多园友也慷慨解囊,也提出了很多建议,但并没有很多实质性的后续,相信大家应该也看到了。 为什么写这篇文章呢?因为最近看到了一个评论,园友是这样写的: 我觉得写的很好,博客园是平台,我们
作为博主和曾经员工,谈谈近期的园子 作为博主和曾经员工,谈谈近期的园子 作为博主和曾经员工,谈谈近期的园子
一次基于AST的大规模代码迁移实践
在研发项目过程中,我们经常会遇到技术架构迭代更新的需求,通过技术的迭代更新,让项目从新的技术特性中受益,但由于很多新的技术迭代版本并不能完全向下兼容,包含了很多非兼容性的改变(Breaking Changes),因此我们需要设计一款工具,帮助我们完成大规模代码自动迁移问题。本文简单阐述了基于AST的
一次基于AST的大规模代码迁移实践 一次基于AST的大规模代码迁移实践 一次基于AST的大规模代码迁移实践
三大硬核方式揭秘:Java如何与底层硬件和工业设备轻松通信!
大家好,我是V哥,程序员聊天真是三句不到离不开技术啊,这不前两天跟一个哥们吃饭,他是我好多年前的学员了,一直保持着联系,现在都李总了,在做工业互联网相关的项目,真是只要 Java 学得好,能干一辈子,卷死的是那些半吊子。 感谢李总给我分享了工业互联网项目的事情,收获很多,今天的内容来聊一聊 Java
.NET 工具库高效生成 PDF 文档
前言 QuestPDF 是一个开源 .NET 库,用于生成 PDF 文档。使用了C# Fluent API方式可简化开发、减少错误并提高工作效率。利用它可以轻松生成 PDF 报告、发票、导出文件等。 项目介绍 QuestPDF 是一个革命性的开源 .NET 库,它彻底改变了我们生成 PDF 文档的方
.NET 工具库高效生成 PDF 文档 .NET 工具库高效生成 PDF 文档 .NET 工具库高效生成 PDF 文档
SimpleRAG-v1.0.3:增加文件对话功能
Kimi上有一个功能,就是增加文件之后对话,比如我有如下一个私有文档: 会议主题:《如何使用C#提升工作效率》 参会人员:张三、李四、王五 时间:2024.9.26 14:00-16:00 会议内容: 1. 自动化日常任务 许多日常任务可以自动化,从而节省时间和精力。例如,如果你需要定期处理大量数据
SimpleRAG-v1.0.3:增加文件对话功能 SimpleRAG-v1.0.3:增加文件对话功能 SimpleRAG-v1.0.3:增加文件对话功能
基础数据结构之递归
递归 1) 概述 定义 计算机科学中,递归是一种解决计算问题的方法,其中解决方案取决于同一类问题的更小子集 In computer science, recursion is a method of solving a computational problem where the solution
基础数据结构之递归 基础数据结构之递归 基础数据结构之递归
仅需6步,实现虚拟物体在现实世界的精准放置
增强现实(AR)技术作为一种将数字信息和现实场景融合的创新技术,近年来得到了快速发展,并在多个应用领域展现出其独特的魅力。比如在教育行业,老师可以通过虚拟现实场景生动直观地帮助学生理解抽象概念;在旅游行业,AR技术还能虚拟历史文化场景、虚拟导航等,为游客提供更加沉浸的互动体验。 然而,对于应用来说,
仅需6步,实现虚拟物体在现实世界的精准放置 仅需6步,实现虚拟物体在现实世界的精准放置 仅需6步,实现虚拟物体在现实世界的精准放置
博客园终身会员小福利,送华为云服务器
最近我们和华为云总经销商浙江杭云网络科技有限公司达成了合作,准备从10月开始做一些华为云的代理业务,增加园子的收入来源。 在做这个业务之前,先给园子的终身会员送点华为云服务器作为小福利,这次只申请到100台,先到先得,送完为止。 赠送的云服务器配置如下: 终身VIP会员 :送1核2G1M华为云服务器
博客园终身会员小福利,送华为云服务器