
中秋前就决定要开FastAPI的学习了还是一直拖到国庆前才开始。还好作者之前有过SpringBoot框架及其相关知识的学习和实践花了大概两周时间一般看知识点一遍跟着敲中间有疑惑的地方就给智能体帮我解惑也是顺利的学习完了FastAPI这个后端框架。整体上还是和SpringBoot有相似之处但是其中某些功能的实现还是有区别看视频是自己也总结了一些难点或者是一些我觉得算是“优雅”的实现本篇文章就围绕这些点来谈一谈。首先第一个难点就是依赖注入这是一个将通用逻辑或者代码用于路由函数或者别的函数的参数传入并可以自动执行封装好的代码体逻辑的一个实现。下面就直接拿后端项目中的路由函数来演示其作用以及原理router.get(/info) async def get_user_info(user: User Depends(get_current_user)): # 获取用户信息逻辑验证用户是否存在 - 获取用户信息 - 响应结果: 依赖注入 return success_response(message获取用户信息成功,dataUserInfoResponse.model_validate(user))这是一个获取用户信息的路由函数可以看到传入的参数是一个类型为User的对象并有默认值默认值就是由依赖注入实现注意这里使用依赖注入是调用了Depends这个方法传入的值是要注入的函数名而不是对函数的调用如get_current_user(),添加了括号后表示对函数的调用。下面就是get_current_user函数的方法体async def get_current_user(authorization: str Header(...,aliasAuthorization), db:AsyncSessionDepends(get_db)): # Bearer xxxxx # tokenauthorization.split( )[1] token authorization.replace(Bearer ,) user await get_user_by_token(db, token) if not user: raise HTTPException(status_codestatus.HTTP_401_UNAUTHORIZED,detail无效的令牌或令牌过期) return user由于篇幅原因原谅作者详细的内容就不在这里说了大概就是从前端返回的请求头中提取token进行对用户账号的鉴权。学过后端的同学都知道鉴权在大量的接口会用到是需要高频被调用的逻辑片段依赖注入就是通过fastapi框架来对注入的函数进行调用来实现对鉴权的便捷使用调用的时刻就是在执行当前函数的方法体之前而且可以嵌套依赖注入会深度执行。上面的代码就是在被注入的get_current_user参数中也有db:AsyncSessionDepends(get_db)这一层依赖注入。嵌套的注入就可以实现逻辑重复调用的嵌套作者认为是很优雅的一种方式呢~在路由中使用ORM也是一个难点但我觉得理解了之后才能更好的在后面去运用它。ORM是一种编程技术通过使用操作对象的方式而不是使用sql语句来操作数据库。在上面的代码已经出现了db:AsyncSessionDepends(get_db)这样的对象类型AsyncSession对象其实就是数据库的会话对象这个对象怎么生成的呢我们先看下面的代码ASYNC_DATABASE_URL mysqlaiomysql://root:123456localhost:3306/FASTAPI_first?charsetutf8 async_engine create_async_engine( ASYNC_DATABASE_URL, echoTrue, #可选输出sql日志 pool_size10, # 设置连接池活跃的连接数 max_overflow20, # 允许额外的连接数 ) AsynccsessionLocal async_sessionmaker( bindasync_engine, # 绑定数据库引擎 class_AsyncSession, # 指定会话类 expire_on_commitFalse, # 提交后回话不过期不会重新查询数据库 ) # 依赖项 async def get_database(): async with AsynccsessionLocal() as session: try: yield session #返回处理数据库会话给路由处理函数 await session.commit() # 提交事务 except Exception: await session.rollback() # 有异常回滚 raise finally: await session.close() #关闭会话第一个部分先运行好数据库的服务并得到url在传入创建异步引擎的方法中并配置一些参数第二部分就是创建会话工厂对象了绑定数据库引擎后指定会话类设置会话生命等参数后创建一个AsyncSession工厂实例其被调用后会创建AsyncSession数据库会话对象。重点是第三部分就是依赖项看到其逻辑是先异步创建一个会话对象然后再返回处理数据库会话给路由处理函数这里是什么意思呢我们结合下面的路由函数代码来讲一下app.get(/book/get_book/{bookid}) async def get_book(book_id:int,db : AsyncSession Depends(get_database)): result await db.execute(select(Book).where(Book.id book_id)) book result.scalar_one_or_none() return book这里的书籍查询路由函数就是使用了依赖注入get_database这个函数来实现对数据库中对应id书籍的信息的检索。下面是整个运行的时序前端发送请求后FastAPI 看到 db 参数是 Depends(get_database)就调用调用 get_database()走到yield session这里时将创建的session这个对象给到db然后在get_book这个路由函数的方法体中就拿到数据库的会话对象就可以对数据库进行增删改查的操作在得到数据或者对数据库操作完、路由函数return返回值后get_database才从ield 处恢复执行await session.commit()提交事务到数据库如果有异常则走await session.rollback()进行事务回滚。最终await session.close()关闭会话。这就实现了ORM在路由中的使用。最后就一起看一个优雅的片段吧queryupdate(User).where(User.username username).values(**user_data.model_dump( exclude_unsetTrue, exclude_noneTrue) )这个片段实现了对用户信息的更新因为用户信息不止一个字段如果要一个个去更新的话会很麻烦这里很巧妙的实现了信息更新首先user_data是一个UserUpdateRequest类型的实例这个类型的定义如下class UserUpdateRequest(BaseModel): nickname: str None avatar: str None gender: str None bio: str None phone: str Noneupdate(User).where(User.username username)在通过用户名定位到对应用户对象在数据库中的位置后首先对user_data这个实例调用model_dump将pydantic类型对象转换为字典例如{“nickname”: “小明”}这样的形式后面的exclude_unsetTrue, exclude_noneTrue配置则是对用户没传或者传入的值是None则不转化最后使用解包就可以实现对用户新赋值的信息的修改而其他的信息保留的效果。比如.values({“nickname”: “小明”, “bio”: “你好”})解开.values(nickname“小明”, bio“你好”)在python中对解包使用熟练的话会有一些妙用。好了这就是我在学习fastapi框架中遇到的难点以及一些特别的实现还有一些特性由于作者原来学习过SpringBoot所以理解和吸收起来没有太大难度如果大家之前没接触过后端开发学习的时候还是建议多花一些时间去理解框架中的功能或者特性是怎么实现的哦。因为作者刚开始就是学后端出身很喜欢后端那种严丝合缝的逻辑感如果有不懂的地方必须要弄懂才会踏实。我觉得在ai时代理解内核原理不是无用之举反而是提升自己的一种锻炼方式。这里是般逗如果觉得本篇文章还可以请大家留下一个赞如有谬误还请指正。我们下一篇再见٩(ˊᗜˋ)و✧