FastAPI
前言
因为我本身是学习Java的,如果你也是,那么你学习 FastAPI 会非常顺畅!很多概念几乎可以无缝迁移。
让我用熟悉的 Spring Boot 视角来帮你快速建立对应关系:
核心概念对应表(Spring Boot → FastAPI)
Spring Boot 概念
FastAPI 对应概念
相似度
@RestController
@app.get()/@app.post() 等路由装饰器
★★★★★
@RequestMapping
路径参数和装饰器(@app.api_route)
★★★★☆
@Autowired
Depends() 依赖注入
★★★★☆
@Component/@Service
普通函数 + Depends()
★★★★☆
@Repository
数据库操作函数/类
★★★★☆
@Configuration
启动时初始化代码/依赖项
★★★☆☆
@Bean
使用 lifespan 或单例依赖
★★★☆☆
Interceptor/Filter
依赖项或中间件
★★★★☆
@ControllerAdvice
异常处理器(@app.exception_handler)
★★★★☆
@Valid 和 DTO
Pydantic 模型验证
★★★★★
application.properties
环境变量或 .env 文件
★★★★☆
Spring Security
依赖项 + OAuth2 工具
★★★★☆
你会立即感到熟悉的几个方面
1. 注解式开发 → 装饰器开发
1 2 3 4 @app.get("/users/{id}" ) def get_user (id : int , db: Session = Depends(get_db ) ): return db.query(User).filter (User.id == id ).first()
2. 依赖注入的使用
1 2 3 4 5 6 7 8 9 10 11 12 13 class UserService : def get_user (self, user_id: int ): return {"id" : user_id, "name" : "John" } user_service = UserService() @app.get("/users/{id}" ) def read_user (id : int , service: UserService = Depends(lambda : user_service ) ): return service.get_user(id )
3. 数据验证(DTO → Pydantic)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 from pydantic import BaseModelclass UserCreate (BaseModel ): username: str email: str age: int @validator('email' ) def validate_email (cls, v ): if '@' not in v: raise ValueError('Invalid email' ) return v @app.post("/users/" ) def create_user (user: UserCreate ): return {"message" : "User created" }
需要稍作调整的思维模式
更函数式,更少“仪式感”
不需要定义接口
不需要 getter/setter
没有复杂的 XML 配置
更直接的请求-响应
参数直接从函数参数获取
返回值直接就是响应体
异步支持是天生的(async/await)
更灵活的依赖注入
可以是函数,可以是类,都可以注入
可以基于路径参数、查询参数、header 等动态创建依赖
学习建议
直接找对应关系 :每当你想“在 Spring Boot 里我会怎么做”,就去查 FastAPI 的对应方案
从 Pydantic 开始 :这是 FastAPI 的“杀手锏”,类似 Lombok + Validation 的超强组合
理解 Python 的特性 :类型提示、装饰器、async/await - 这些是 FastAPI 强大的基础
别怕写“简单”代码 :Python 代码看起来比 Java 简单,但功能一样强大
快速入门路径
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 @app.get("/hello" ) def hello (name: str = "World" ): return {"message" : f"Hello {name} " } def get_db (): db = SessionLocal() try : yield db finally : db.close() @app.get("/items" ) def get_items (db: Session = Depends(get_db ) ): return db.query(Item).all () oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token" ) def get_current_user (token: str = Depends(oauth2_scheme ) ): return user @app.get("/users/me" ) def read_me (current_user = Depends(get_current_user ) ): return current_user
好消息是…
你的 Spring Boot 经验有 80% 可以直接迁移!
REST API 设计
分层架构(Controller/Service/Repository)
依赖注入的价值
数据验证的重要性
配置管理
错误处理
FastAPI 只是用更 Pythonic、更简洁的方式实现了相同的理念。你会发现在 FastAPI 中实现同样的功能,代码量可能只有 Spring Boot 的 1/3 到 1/2,但功能和性能一样强大。
我们学习java学的是理念,FastAPI 只是换了种更轻量、更现代的语言和语法来实现它。
下面是我的笔记~
FastAPI 入门 - FastAPI 框架
Python 版本最低3.8 推荐3.10以上 我是用3.13
Python环境
为了适应各种Python版本,这里使用MiniConda 来作为Python环境,MiniConda 可以在创建虚拟环境的时候指定Python 版本号,并且没有Anaconda 那么多乱七八糟的第三方库
一:MiniConda
Miniconda - Anaconda
Download Success - post download | Anaconda
安装完后要将路径添加到环境变量当中
1 2 3 4 5 6 # 根路径 D: \miniconda# Scripts 路径 D: \miniconda\Scripts# bin路径 D: \miniconda\Library\bin
验证:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 C:\Users \Lenovo >conda <==== 输入conda usage : conda -script.py [-h ] [-v ] [--no -plugins ] [-V ] COMMAND ...conda is a tool for managing and deploying applications , environments and packages .options : -h , --help Show this help message and exit . -v , --verbose Can be used multiple times . Once for detailed output , twice for INFO logging , thrice for DEBUG logging , four times for TRACE logging . --no -plugins Disable all plugins that are not built into conda . -V , --version Show the conda version number and exit . commands : The following built -in and plugins subcommands are available . COMMAND activate Activate a conda environment . clean Remove unused packages and caches . commands List all available conda subcommands (including those from plugins ). Generally only used by tab -completion . compare Compare packages between conda environments . config Modify configuration values in .condarc . content -trust Signing and verification tools for Conda create Create a new conda environment from a list of specified packages . deactivate Deactivate the current active conda environment . doctor Display a health report for your environment . env Create and manage conda environments . export Export a given environment info Display information about current conda install . init Initialize conda for shell interaction . install Install a list of packages into a specified conda environment . list List installed packages in a conda environment . menuinst A subcommand for installing and removing shortcuts via menuinst . notices Retrieve latest channel notifications . package Create low -level conda packages . (EXPERIMENTAL ) remove (uninstall ) Remove a list of packages from a specified conda environment . rename Rename an existing environment . repoquery Advanced search for repodata . run Run an executable in a conda environment . search Search for packages and display associated information using the MatchSpec format . token Set repository access token and configure default_channels tos A subcommand for viewing , accepting , rejecting , and otherwise interacting with a channel 's Terms of Service (ToS ). This plugin periodically checks for updated Terms of Service for the active /selected channels . Channels with a Terms of Service will need to be accepted or rejected prior to use . Conda will only allow package installation from channels without a Terms of Service or with an accepted Terms of Service . Attempting to use a channel with a rejected Terms of Service will result in an error . update (upgrade ) Update conda packages to the latest compatible version . C :\Users \Lenovo >
二:虚拟环境
默认情况下,我们直接通过pip install 的方式将包安装在系统级别的Python环境中,这样存在一个问题,就是如果有个老项目用FastAPI是老版本做的,然后你现在想用最新的FastAPI版本来开发新项目,这时候就会碰到一个问题,如何在电脑中同事拥有两套环境?这个时候就是使用我们的虚拟环境来解决这个问题。
首先,我们创建一个基于Python 3.13 版本的虚拟环境:
1 2 conda create -n fastapi-env python=3.13
通过下列命令可以管理虚拟环境:
1 2 3 4 5 6 7 8 9 10 11 conda env list conda env remove -n [虚拟环境名称] conda activate [虚拟环境名称] conda deactivate
三:设置pip源
默认情况下,使用pip命令会从python官网上下载,由于Python官网服务器在国外,下载速度有点慢,我们可以改为国内滴,比如清华,搜索引擎搜索一下也有很多其他的
1 pip config set global .index-url https://pypi.tuna.tsinghua.edu.cn/simple
结果:
1 2 3 4 C:\Users \Lenovo >conda activate fastapi -env (fastapi -env ) C :\Users \Lenovo >pip config set global.index -url https ://pypi.tuna.tsinghua.edu.cn /simple Writing to C :\Users \Lenovo \AppData \Roaming \pip \pip.ini
开发工具
PyCharm
这个不多说啦
我是教育邮箱申请的pro
或者你可以去某宝购买。
Mysql
javaer应该都会的
Navicat
也可以使用其他的数据库可视化软件
FastAPI 介绍
一:FastAPI 简介
FastAPI 是一个高性能的 Python Web 框架,旨在为开发人员提供快速、简洁且强大的 API 开发体验。它于 2017 年由 Sebastian Ramirez 发布,旨在解决当时市场上现有框架在处理 HTTP 请求和响应时的复杂性和维护困难问题。
Sebastian Ramirez 在开发 FastAPI 时,面临着构建 API 的挑战,他发现现有的框架在处理 HTTP 请求和响应时过于复杂,难以维护。因此,他决定开发一个更简洁、更易于使用的框架,以帮助其他开发人员更专注于业务逻辑,而不是处理 HTTP 请求和响应。
FastAPI 支持异步编程 ,这意味着它可以更有效地处理并发请求,提高应用程序的性能。此外,FastAPI 还支持多种数据库和数据存储后端,如 PostgreSQL、MySQL、SQLite、MongoDB 等,以及 ORM 框架,如 SQLAlchemy。这使得开发者可以轻松地将 FastAPI 与各种数据库集成,构建强大的数据驱动应用程序。
许多知名的公司和项目已经开始使用 FastAPI,包括 Google、Netflix、Amazon、Dropbox 等。这些公司在使用 FastAPI 时,都对其高性能和简洁性给予了高度评价。
FastAPI 的基准测试成绩也证明了其高性能。根据官方的基准测试结果,FastAPI 在处理并发请求时,其性能优于其他流行的 Web 框架,如 Flask 和 Django。这使得 FastAPI 成为构建高性能 Web 应用程序和 API 的理想选择。
Django、Flask 和 FastAPI 三大框架的特点:
功能:Django > Flask > FastAPI
性能:FastAPI > Flask > Django
二:FastAPI的优点
快速 :与NodeJS和Go性能相当,是最快的Python web框架之一。
高效编码 :提升功能开发速度200%至300%。
更少bug :减少约40%开发者人为错误。
智能 :编辑器自动补全以减少调试时间。
简单 :易使用和学习,读文档时间更短。
简短 :代码重复最小化,通过参数声明实现丰富功能,bug更少。
健壮 :生产可用级别代码,含自动生成的交互式文档。
标准化 :基于OpenAPI和JSON Schema。
三:安装
使用下面这个命令即可安装:
1 pip install "fastapi[standard]"
四:一个最简单的FastAPI程序
在Pycharm中选择FastAPI项目新建
当然了记得创建.gitignore 因为ide会自带一些文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 from fastapi import FastAPIapp = FastAPI() @app.get("/" ) async def root (): return {"message" : "Hello World" } @app.get("/hello/{name}" ) async def say_hello (name: str ): return {"message" : f"Hello {name} " }
Uvicorn
uvicorn是一个高性能的异步web服务器。我们也可以使用uvicorn来直接运行FastAPI项目。首先通过以下命令安装uvicorn:
1 pip install "uvicorn[standard]"
然后可以通过下面命令运行项目:
1 uvicorn main:app --reload
测试API
另外我们可以在项目根路径下test_main.http 中测试我们写的API是否有错误
具体项目代码(后续所有代码都放在这里):yjyrichard/fastapi-learning: fastapi学习代码
Pydantic介绍
在其他web框架中,比如Django或Flask,我们通过定义表单类来校验数据。而在FastAPI中,我们使用Pydantic来实现这一功能。
Pydantic的特点:
由类型提示支持 :少学习、代码少、与IDE工具集成。
速度快 :Rust核心验证,Python最快数据验证库之一。
JSON模式 :与其他工具集成。
生态系统丰富 :PyPI约8000个包,含FastAPI等流行库。
Battle测试 :月下载超7000万次,被多家大型科技公司使用。
安装
由于FastAPI依赖Pydantic,因此在安装FastAPI时会把pydantic也一起安装了。
基本使用
Pydanyic 是通过定义模型,以及在模型中指定字段来对值进行校验的,示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 from datetime import datefrom typing import List from pydantic import BaseModel, ValidationErrorclass User (BaseModel ): """ 定义一个名为User的模型,它继承自pydantic.BaseModel。 这个类定义了我们期望的数据结构、类型和约束。 """ id : int name: str = 'John Doe' date_joined: date | None departments: List [str ] | None print ("--- 场景一:使用有效数据 ---" )valid_data = { 'id' : 123 , 'date_joined' : '2023-06-01' , 'departments' : ['技术部' , '产品部' ] } try : user = User(**valid_data) print ("✅ 数据验证成功!" ) print (f"用户ID: {user.id } " ) print (f"用户姓名: {user.name} " ) print (f"加入日期: {user.date_joined} (类型: {type (user.date_joined)} )" ) except ValidationError as e: print ("❌ 数据验证失败!" ) print (e) print ("\n" + "=" *50 + "\n" )print ("--- 场景二:使用无效数据并捕获错误 ---" )invalid_data = { 'id' : 'abc' , 'name' : 456 , 'date_joined' : '2023-13-01' , 'departments' : '不是列表' } try : user_invalid = User(**invalid_data) print ("✅ 数据验证成功!" ) except ValidationError as e: print ("❌ 数据验证失败!捕获到 ValidationError。" ) print ("\n--- 错误摘要 ---" ) print (e) print ("\n--- 详细错误列表 ---" ) error_list = e.errors() for i, error in enumerate (error_list, 1 ): print (f"错误 {i} :" ) print (f" - 位置: {' -> ' .join(map (str , error['loc' ]))} " ) print (f" - 信息: {error['msg' ]} " ) print (f" - 类型: {error['type' ]} " ) print ("-" * 20 )
请求数据
请求数据包括有路由参数,Body参数,以下分别进行讲解:
这个跟java没有什么区别 直接来看例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 from fastapi import FastAPI, Body, Query, Path, Form, File, UploadFilefrom pydantic import BaseModel, Fieldfrom typing import Annotatedapp = FastAPI() @app.get("/items/{item_id}" ) async def read_item (item_id: int ): return {"item_id" : item_id} @app.get("/users/" ) async def read_users (q: Annotated[str | None , Query(max_length=50 )] = None ): if q: return {"query" : q} return {"message" : "No query parameter provided" } class Item (BaseModel ): name: str description: str | None = None price: float tax: float | None = None @app.post("/items/" ) async def create_item (item: Item ): return item @app.put("/items/{item_id}" ) async def update_item ( item_id: Annotated[int , Path(title="The ID of the item to update" , ge=1 )], q: str | None = None , item: Annotated[Item, Body(embed=True )] ): results = {"item_id" : item_id, "item" : item} if q: results["q" ] = q return results @app.post("/login/" ) async def login (username: str = Form( ), password: str = Form( ) ): return {"username" : username} @app.post("/uploadfile/" ) async def create_upload_file (file: UploadFile = File(... ) ): return { "filename" : file.filename, "content_type" : file.content_type } @app.post("/files/" ) async def create_file ( file: bytes = File( ), description: str = Form(... ) ): return { "file_size" : len (file), "description" : description }
依赖注入
依赖注入可以让我们的视图函数在执行之前先执行一段逻辑代码,这段逻辑代码可以返回新的值给视图函数。在以下场景中可以使用依赖注入:
共享业务逻辑(复用相同的代码逻辑)
共享数据库连接
实现安全、验证、角色权限
等等。
总之,就是将一些重复性的代码单独写成依赖,然后在需要的视图函数中注入这个依赖。
因为我之前是学习Java的 这样解释我反而有点看不太懂
跟spring的核心理念是相同的意思是:
“控制反转(IoC)”和“依赖倒置(DIP)”:将对象的创建和管理权交给框架,使用者只声明“我需要什么”,框架负责“提供什么”。
springboot这样写嘛:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Service public class UserService { public User getUser (Long id) { } } @RestController public class UserController { @Autowired private UserService userService; @GetMapping("/user/{id}") public User getUser (@PathVariable Long id) { return userService.getUser(id); } }
fastapi这样写:
1 2 3 4 5 6 7 8 9 10 def get_current_user (token: str = Depends(oauth2_scheme ) ): return user @app.get("/users/me" ) def read_users_me (current_user: User = Depends(get_current_user ) ): return current_user
总之:就是别总是 “new ”啦 找框架要吧。
将一些重复性的代码单独写成以来,任何在需要的视图函数中,注入这个依赖。示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 from fastapi import Dependsfrom typing import Dict async def page_common (page: int =0 ,size: int =10 ): return {"page" : page,"size" : size} @app.get("/user/list" ) async def user_list (page_params: Dict =Depends(page_common ) ): page = page_params["page" ] size = page_params["size" ] return {"page" : page,"size" : size}
APIRouter
在FastAPI项目中,我们不可能把所有视图都放到main.py 文件中,这时候久需要将视图进行分类,任何同类的放到一个单独的子路由下。在FastAPI 中可以使用 APIRouter 类进行实现。【好比 java里面的 [业务名称]Controller 这样看起来更加清晰嘛】
新建一个包:routers
里面新建两个py文件分别为:article.py 和 user.py
user.py
1 2 3 4 5 6 7 8 9 10 11 12 13 from fastapi import APIRouterrouter = APIRouter(prefix="/user" , tags=["user" ]) @router.get("/list" ) async def user_list (): return {"users" : ["zs" ,"ls" ]} @router.get('/{user_id}' ) async def user_detail (user_id ): return {"user_id" : user_id}
article.py 也差不多 就不粘贴了
现在还没有跟main.py进行关联
1 2 3 4 5 6 from fastapi import FastAPIfrom routers.user import router as user_routerfrom routers.article import router as article_router app = FastAPI() app.include_router(user_router) app.include_router(article_router)
这个配置方式让我感觉跟vue很像
想象成组装一台电脑:
FastAPI/Vue 方式 (模块化组装):
1 2 3 4 1. 买一个空机箱(app = FastAPI() / createApp())2. 买独立显卡(user_router) 3. 买独立内存条(article_ router)4. 组装起来(app.include_router())
灵活 :需要什么装什么
Spring Boot 方式 (一体化方案):
1 2 3 1. 买品牌整机(@SpringBootApplication)2. 开机即用(自动扫描所有组件)3. 配置都在说明书里(application.properties)
省心 :开箱即用,功能齐全
学习迁移建议
FastAPI 的 app ≈ Vue 的 app ≈ Spring Boot 的启动类
都是应用的核心容器
都负责全局配置
都是模块注册的中心
FastAPI 的 APIRouter ≈ Vue 的组件 ≈ Spring Boot 的 @Controller
都是功能模块
都可以独立开发和测试
都可以被主应用"挂载"
最大的区别 :
FastAPI/Vue : 显式注册(你要手动 include_router)
Spring Boot : 隐式注册(自动扫描 @Controller)
现代框架都在向 “核心应用 + 模块化插件” 的模式发展。这种模式让代码更清晰、更易维护,也让学习曲线更平滑——学会一个,其他的就很容易理解了。
app = FastAPI() 就是 FastAPI 世界的 “Spring Boot Application”,是整个应用的启动器和配置中心。**
数据库连接和模型
在Python框架中,我们通常会使用ORM(Object Relationship Mapping)框架来操作数据库。目前主流的ORM框架有:SQLALchemy、Peewee ORM、Pony ORM、GINO、Tortoise ORM、orman等。而SQLALchemy是功能最强大,且社区最活跃的ORM库,并且还支持异步,因此我选择用SQLALchemy作为操作数据库的ORM框架。
另外,FastAPI作者开发了一个ORM框架叫做SQLModel,但是这个框架目前来说还不完善,文档都还处于开发期间,它底层也是基于SQLALchemy Core来实现的。SQLAlchemy文档地址为:https://www.sqlalchemy.org/
安装
1.安装sqlalchemy
通过以下命令安装:
1 pip install "sqlalchemy[asyncio]"
将会安装异步版本的sqlalchemy
然后再执行以下命令安装aiomysql 驱动:
1 2 3 # 同步:mysqlclient # 异步:aimysql pip install aiomysql
2.安装cryptography
使用Python连接MySQL需要用cryptography对密码进行加密,所以还需要安装以下包:
1 pip install cryptography
创建连接
配置连接参数
使用SQLAlchemy 连接数据库,是通过设置一个固定格式的字符串来实现的。mysql+aiomysql 为例,那么其连接格式如下:
1 DB_URL = "mysql+aiomysql://用户名:密码@主机名:端口号/数据库名称?charset=utf8mb4"
示例如下:
1 DB_URL = "mysql+aiomysql://root:root@127.0.0.1:3306/bookdb?charset=utf8mb4"
创建Engine 对象
SQLAlchemy 中的 Engine 对象,它负责管理数据库连接的创建(并不直接操作数据库),连接池的维护,SQL语句的翻译等。Engine对象在整个程序中只能有一个。创建Engine对象的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 from sqlalchemy.ext.asyncio import create_async_engineengine = create_async_engine( DB_URI, echo=True , pool_size=10 , max_overflow=20 , pool_timeout=10 , pool_recycle=3600 , pool_pre_ping=True , )
创建会话工厂
使用 sqlalchemy_orm.sessionmarker 类来创建会话工厂,这个会话工厂实际就是Session 或者它的子类,以后如果要操作数据库,那么就需要创建一个会话工厂的对象 (即:Session类的对象),来完成相关操作。示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 from sqlalchemy.orm import sessionmakerfrom sqlalchemy.ext.asyncio import AsyncSessionAsyncSessionFactory = sessionmaker( bind=engine, class_=AsyncSession, autoflush=True , expire_on_commit=False )
创建模型
定义Base 类
Base 类是所有ORM Model 类的父类,一个ORM Model 类对应数据库中的一张表。ORM Model 中的一个Column 类属性对应数据库表中的一个字段。Base类的生成可以使用 sqlalchemy.ext.declarative.declarative_base 函数来实现,也可以继承 sqlalchemy.MetaData 类,实现自己的子类,并在子类中编写约束规范。
示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 from sqlalchemy.orm import DeclarativeBasefrom sqlalchemy import MetaDataclass Base (DeclarativeBase ): metadata = MetaData(naming_conventions={ "ix" : 'ix_x(column_0_label)s' , "uq" : "uq_x(table_name)s_x(column_0_name)s" , "ck" : "ck_x(table_name)s_x(constraint_name)s" , "fk" : "fk_x(table_name)s_x(column_0_name)s_x(referred_table_name)s" , "pk" : "pk_x(table_name)s" })
创建ORM模型
这里我们以创建一个User模型为例来说明模型的创建:
1 2 3 4 5 6 7 8 9 10 11 from typing import Optional from sqlalchemy import Integer, String, selectfrom sqlalchemy.orm import Mapped, mapped_columnclass User (Base ): __tablename__ = 'user' id : Mapped[int ] = mapped_column(Integer, primary_key=True , autoincrement=True ) email: Mapped[str ] = mapped_column(String(100 ), unique=True , index=True ) username: Mapped[str ] = mapped_column(String(100 )) password: Mapped[str ] = mapped_column(String(200 ))
模型关系
这里我们使用外键来实现一对一,一对多和多对多,示例代码如下: