文章目录1. 概览2. 运行和测试3. 路由和分包4. 请求和响应4.1 路径参数从URL路径中取值顺序很重要4.2 查询参数从「」后面取值默认值可选参数4.3 请求体4.4 表单提交4.5 文件上传指定是bytes类型小文件UploadFile 对象上传大文件1. 概览python web 框架FastAPI: 轻量级高内聚低耦合。Django: 重耦合度高。Flask最轻。框架特点适用场景FastAPI轻量级原生异步API/前后端分离/微服务Django重支持异步但加入较晚完整网站后台、用户系统Flask很轻默认只提供路由、请求处理小项目、学习Web原理FastAPI的两个核心组件Starlette: 负责Web核心功能。包括路由(URL)、请求(Request)、响应(Response)、中间件(Middleware)、异步支持(ASGI)。Pydanic: 数据校验 数据解析frompydanticimportBaseModelclassUser(BaseModel):name:strage:int# 如果传入数据错误类型(ageabc)会自动报错2. 运行和测试示例 fromfastapiimportFastAPI# 创建FastAPI实例appFastAPI()# 查询用户app.get(/users/{user_id})defget_user(user_id:int):return{user_id:user_id,name:zhangsan,age:20}# 创建用户app.post(/users/{user_id})defcreate_user(user_id:int):return{message:user created,user_id:user_id}# 更新用户app.put(/users/{user_id})defupdate_user(user_id:int):return{meaasge:user updated,user_id:user_id}# 删除用户app.delete(/users/{user_id})defdelete_user(user_id:int):return{message:user deleted,user_id:user_id}运行点击Pycharm中的「编辑配置」点击左上角「」按钮选择「FastAPI」编辑名称选择运行文件并且加上端口号--portXXXX点击右下角「服务」按钮或快捷键Alt8就可以看到当前FastAPI并运行测试专业的测试工具postman点击「GET」下拉框选择请求方式输入访问地址点击「Send」按钮在body部分就可以看到返回的信息了。自带的API文档生成器访问 http://127.0.0.1:8000/docs 交互式 API 文档会自动更新并包含新的请求体。点击「Try it out」按钮它允许你填写参数并直接与 API 交互然后点击「Execute」按钮界面会与你的 API 通信、发送参数、获取结果并在屏幕上展示四种请求方式GET 是“获取数据”的请求方式。它只负责从服务器拿数据不会对数据做修改。比如你访问用户信息就是用 GET。它不会改变数据而且可以被浏览器缓存。POST 是“创建数据”。当你想新增一条数据比如创建一个新用户就用 POST。它通常会把数据放在请求体里可以理解为“藏在请求里面发送过去”而不是写在 URL 里。POST 每次请求通常都会产生新的数据。PUT 是“更新数据”。当你想修改一个已经存在的资源比如修改用户的名字或年龄就用 PUT。DELETE 是“删除数据”。当你想删除某个资源比如删除一个用户就用 DELETE。3. 路由和分包路由就是“把不同的请求路径分配给对应的函数处理“而分包思想就是“把代码按功能拆分到不同文件中避免所有代码堆在一个文件里”。FastAPI 里通常用APIRouter来实现分包。开发步骤创建API路由器实例# user包下的urls.py文件user_routerAPIRouter()定义GET请求路由# user包下的urls.py文件user_router.get(/{user_id})asyncdefget_user(user_id:int):print(user_id)return{user_id:user_id,name:zhangsan,age:20}导入路由其中prefix是请求路径前缀即让所有路径以/xxx开头tags表示路由标签# 主文件main.pyapp.include_router(user_router,prefix/users,tags[用户管理])4. 请求和响应在 FastAPI 中请求就是“客户端发过来的数据”响应就是“服务器返回给客户端的数据”。简单理解就是你给我什么请求我回你什么响应。4.1 路径参数从URL路径中取值请求路径中带参数user_router.get(/{user_id})defget_user(user_id:int):return{user_id:user_id,}测试注意函数接收并返回的值是1001int不是1001str。FastAPI 通过类型声明自动将HTTP请求中的字符串转换为Python数据类型。顺序很重要有时路径操作_中的路径是写死的。比如要使用/users/me获取当前用户的数据。然后还要使用/users/{user_id}通过用户 ID 获取指定用户的数据。由于_路径操作_是按顺序依次运行的因此一定要在/users/{user_id}之前声明/users/meuser_router.get(/me)asyncdefread_user_me():return{user_id:the current user}user_router(/{user_id})asyncdefread_user(user_id:str):return{user_id:user_id}否则/users/{user_id}将匹配/users/meFastAPI 会认为正在接收值为me的user_id参数。4.2 查询参数从「」后面取值声明的参数不是路径参数时路径操作函数会把该参数自动解释为“查询”参数。查询字符串是键值对的集合这些键值对位于 URL 的?之后以分隔。比如http://127.0.0.1:8888/users/?page1000size1001路径后面一定要加/。user_router.get(/)defget_user(page:int1,size:int10):return{page:page,size:size}测试在postman的Params中填写参数page和size默认值查询参数不是路径的固定内容它是可选的还支持默认值。上例用page1和size10设定默认值。访问URL:http://127.0.0.1:8888/users/与访问以下地址相同http://127.0.0.1:8888/users/?page1size10可选参数同理把默认值设为None即可声明可选的查询参数user_router.get(/{page})defget_user(page:int1,size:int|NoneNone):ifsize:return{page:page,size:size}return{page:page}本例中查询参数q是可选的默认值为None。FastAPI可以识别出page是路径参数size不是路径参数而是查询参数。4.3 请求体当你需要从客户端比如浏览器向你的 API 发送数据时会把它作为请求体发送。一般用于 POST 或 PUT比如提交一个 JSON 数据来创建用户。使用pydantic模型来声明请求体classUser(BaseModel):name:strage:intuser_router.post(/)defcreate_user(user:User):returnuser测试的时候选择POST选择传入Body下的raw,传入json:与声明查询参数一样包含默认值的模型属性是可选的否则就是必选的。把默认值设为None可使其变为可选。例如上述模型声明如下 JSON “object”即 PythondictclassUser(BaseModel):name:strage:18|None4.4 表单提交要使用表单首先安装python-multipartpipinstallpython-multipart示例user_router.post(/login/)deflogin(username:strForm(...),password:strForm(...)):return{username:username}选择Body下的form-data并填写表单数据4.5 文件上传使用File定义由客户端上传的文件。同样上传文件需要先安装python-multipart因为上传文件是以「表单数据」发送的。pipinstallpython-multipart指定是bytes类型小文件bytes 的方式是把整个文件一次性读到内存里所以用起来很简单但如果文件很大会占用很多内存不太安全。user_router.post(/upload/)defupload(file:bytesFile()):print(f文件大小为{len(file)})return{size:len(file)}多文件上传user_router.post(/uploads/)defupload_multiple_files(files:List[bytes]File()):# 循环forfileinfiles:print(f文件大小为{len(file)})return{size:[len(file)forfileinfiles]}# 推导式UploadFile对象上传大文件UploadFile 是 FastAPI 推荐的方式它底层用的是“临时文件”不会一次性全部加载到内存更适合处理大文件而且还提供了文件名、文件类型等信息。UploadFile 的 read() 是异步的要记得用await.user_router.post(/file/upload/)asyncdeffile_upload(file:UploadFile):iffile:print(file.filename,file.content_type)withopen(file.filename,wb)asf:f.write(awaitfile.read())return{filename:file.filename,content_type:file.content_type}多文件user_router.post(/file/uploads/)asyncdeffile_upload(files:List[UploadFile]):forfileinfiles:print(file.filename,file.content_type)withopen(file.filename,wb)asf:f.write(awaitfile.read())