FastAPI 基础篇:请求与响应系统详解

📅 2026/6/26 4:24:46
FastAPI 基础篇:请求与响应系统详解
在Web服务中HTTP请求Request和HTTP响应Response是客户端和服务端交互的核心机制。客户端通过发送请求来获取资源或执行操作服务端则根据请求内容返回相应的响应数据。FastAPI 提供了简洁高效的Request和Response对象帮助开发者方便地处理传入的请求数据和构建返回的响应内容。例如通过Request对象可以轻松获取路径参数、查询参数、请求体、请求头、Cookie 等信息。通过Response对象可以自定义状态码、响应头、响应体并支持 JSON、HTML、纯文本、文件流等多种格式输出。一、请求Request1. 查询参数(Query Parameters)查询参数Query Parameters 是指 URL 中?之后的部分。多个参数之间用分隔基础用法新建一个user/router.pyfromfastapiimportAPIRouter routerAPIRouter(prefix/user,tags[用户])router.get()asyncdefget_users(user_name:str,# 必填参数不填会报错age:int0,# 有默认值的查询参数不传给默认值address:str|NoneNone,# 可选查询参数不传也行):user{user_name:user_name,age:age,address:address}returnuser在main.py中注册fromuser.routerimportrouterasuser_router# 创建fastapi实例appFastAPI()# 注册路由app.include_router(user_router)请求测试必填参数不传会返回错误参数校验FastAPI 通过Query和Annotated为查询参数提供声明式校验能力。开发者可以直接在参数定义处配置长度限制、数值范围、正则匹配等规则并自动生成接口文档无需编写额外的校验代码。在user/router.py新增一个接口router.get(/page)asyncdefpage_users(# 必填参数user_name:Annotated[str,Query(min_length2,max_length20,description用户名长度2~20个字符)],# 有默认值age:Annotated[int,Query(ge0,le150,description年龄范围0~150)]18,# 可选参数address:Annotated[str|None,Query(max_length100,description地址)]None,# 正则校验phone:Annotated[str|None,Query(patternr^1[3-9]\d{9}$,description手机号)]None,# 分页参数page:Annotated[int,Query(ge1,description页码)]1,size:Annotated[int,Query(ge1,le100,description每页条数)]10,):return{user_name:user_name,age:age,address:address,phone:phone,page:page,size:size}在文档上也会体现对应的规则Query 常用参数参数作用示例description描述信息description年龄min_length最小长度min_length2max_length最大长度max_length20pattern正则表达式patternr^\d$ge大于等于ge0gt大于gt0le小于等于le100lt小于lt100alias参数别名aliasuserNamedeprecated标记废弃deprecatedTruePydantic 模型对于参数较多的查询接口推荐使用 Pydantic 模型封装 Query 参数。这样既能享受 Pydantic 的数据校验能力又能让接口定义更加简洁清晰特别适用于分页、筛选等复杂查询场景。新建一个user/schemas.pyfrompydanticimportBaseModel,FieldclassUserQuery(BaseModel):user_name:str|NoneField(defaultNone,max_length20)age:int|NoneField(defaultNone,ge0,le150)address:str|NoneNonepage:intField(default1,ge1)size:intField(default10,ge1,le100)在user/router.py中新增一个测试接口router.get(/page2)asyncdefpage_users2(# 使用Annotated是为了告诉FastAPI# UserQuery 的数据来源于 Query 参数而不是 Request Bodyquery:Annotated[UserQuery,Query()]):# 使用model_dump也会对返回前的对象进行校验。returnquery.model_dump()2. 路径参数路径参数是 URL 路径中的动态部分通常用于标识某个具体资源。FastAPI 会根据函数参数名称自动提取路径中的值并进行类型转换和校验。基础用法router.get(/detail/{user_id})asyncdefget_user_detail(user_id:int):# 路径参数会根据类型注解自动转换return{user_id:user_id}上述接口中{user_id}就是路径参数路径参数可以有多个:router.get(/users/{user_id}/orders/{order_id})asyncdefget_user_order(user_id:int,order_id:int):return{user_id:user_id,order_id:order_id}请求测试需要的int参数如果传字符串就会报错使用 Path 增加校验规则和 Query 参数类似FastAPI 提供了Path用于声明路径参数的校验规则和元数据。router.get(/detail/{user_id})asyncdefget_user_detail(user_id:Annotated[int,Path(ge1,description用户ID)]):return{user_id:user_id}一个注意点# 这是动态路由router.get(/users/{user_name})asyncdefget_user(user_name:str):return{user_name:user_name}# 这是静态路由router.get(/users/hello)asyncdefhello():return{msg:hello}当我访问 GET /users/hello时会执行哪个函数。取决于那个函数写在前面。像上述的写法就会导致永远只会执行到动态路由而静态路由不会执行。所以官方推荐的是静态路由写在前面动态路由写在后面# 这是静态路由router.get(/users/hello)asyncdefhello():return{msg:hello}# 这是动态路由router.get(/users/{user_name})asyncdefget_user(user_name:str):return{user_name:user_name}3. 请求体参数Request Body前面介绍的 Query 参数和 Path 参数都来自 URL 而对于创建、修改等操作需要传递大量结构化数据此时通常使用请求体Request Body。 在 FastAPI 中请求体通常使用Pydantic 模型定义FastAPI 会自动完成请求数据解析 类型转换参数校验 Swagger 文档生成 。基础用法在user/schemes.py中定义UserCreateRequestclassUserCreateRequest(BaseModel):# 定义请求体字段包含参数校验user_name:strField(min_length2,max_length20)age:intField(ge0,le150)在user/router.py新增接口router.post()asyncdefcreate_user(request:UserCreateRequest):returnrequest.model_dump()在文档测试请求体与查询参数混用router.post()asyncdefcreate_user(request:UserCreateRequest,notify:boolFalse):return{user:request.model_dump(),notify:notify}请求POST /user?notifytrue请求体{ user_name: Tom, age: 18 }嵌套对象请求体最大的优势就是支持复杂结构。frompydanticimportBaseModelclassAddress(BaseModel):city:strstreet:strclassUserCreateRequest(BaseModel):user_name:strage:int# 嵌套对象address:Address请求体样例如下{user_name:Tom,age:18,address:{city:Shanghai,street:Pudong}}4. 表单参数Form 参数用于接收表单提交的数据常见于登录、注册等传统 HTML 表单场景数据格式为 application/x-www-form-urlencoded 或 multipart/form-data。基础用法在auth/router.py中新增一个登陆接口routerAPIRouter(prefix/auth,tags[认证])router.post(/login)asyncdeflogin(username:strForm(),password:strForm()):return{username:username}在文档中测试可以看到POST/auth/login Content-Type:application/x-www-form-urlencoded请求体为usernameadminpassword123456Form File 上传UploadFile新增一个表单参数和文件混合的接口router.post(/profile)asyncdefupdate_profile(# ... 是 Python 内置的 Ellipsis 对象FastAPI 只是借用它来表示“必填参数”# FastAPI 全部组件都支持Query(...)Path(...)Form(...)username:strForm(...),age:intForm(...),avatar:UploadFileFile(...)):return{username:username,age:age,file:avatar.filename}当表单中包含文件时 Content-Type就是multipart/form-data5. 请求头HTTP 请求头用于携带元信息比如tokenuser-agentlanguagecontent-type基础用法我们继续在auth/router.py新增一个接口router.get(/headers)asyncdefget_headers(token:str|NoneHeader(defaultNone)):return{token:token}测试一下能成功获取到token一个注意点Header 默认会做自动转换命名。因为 Python 变量不能有-FastAPI会把user_agent转成User-Agentrouter.get(/headers)asyncdefget_headers(token:str|NoneHeader(defaultNone),#可以通过Header(convert_underscoresFalse)关闭自动转换#一般不这样做user_agent:strHeader()):return{token:token,user-agent:user_agent}6. cookieCookie 是浏览器存储在客户端的小数据 浏览器会自动保存 自动随请求发送。基础用法fromfastapiimportCookierouter.get(/cookie)asyncdefget_cookie(session_id:str|NoneCookie(defaultNone)):return{session_id:session_id}在文档上测试cookie发现传了没用。这里切换成专业的api工具测试apifox。二、响应ResponseFastAPI 默认会把你返回的 Python 数据如字典、列表、Pydantic 模型自动转成 JSON 并返回不需要你手动做序列化。如果要返回 HTML、文件或流数据可以使用 FastAPI 提供的专门响应类型如HTMLResponse、FileResponse、StreamingResponse。1. JSONResponse这是FastAPI默认的响应类型content-type:application/json基本用法在src/resp/router.py中新增一个接口fromfastapiimportAPIRouter,Queryfromstarlette.responsesimportJSONResponse routerAPIRouter(prefix/resp,tags[响应测试])router.get(/json)defjson_demo():returnJSONResponse(content{msg:ok,code:200})进行测试定制Response我们也可以对Response对象进行设置来返回具体的内容和响应头响应码等信息。router.get(/json)defjson_demo():respJSONResponse(content{msg:ok,code:200},status_code200,headers{Content-Type:application/json})resp.set_cookie(keysession_id,valueabc123)returnrespresponse_class在 FastAPI 中可以在装饰器上通过response_class和status_code来预先定义响应类型和状态码这样在函数内部只需要返回“原始数据”不需要手动构造 Response使代码更简洁。router.get(/json,status_code200,response_classJSONResponse)defjson_demo():return{msg:ok,code:200}2. HTMLResponse用于返回html网页。响应类型为content-typetext/html;基础用法router.get(/html,response_classHTMLResponse)defhtml_demo():returnh1 stylecolor:redHello FastAPI/h1进行测试3. PlainTextResponse用于返回纯文本。响应类型为content-type:text/plain基础用法router.get(/text)deftext_demo():returnPlainTextResponse(hello world)进行测试4. FileResponse主要用于文件下载浏览器访问会直接下载文件。响应类型为content-disposition:attachment;filenamemy-image.pngcontent-type:image/png基础用法router.get(/download)defdownload():returnFileResponse(# 服务器的文件pathD:/temp/1.png,# 下载的文件名filenamemy-image.png)5. StreamingResponse流式响应一边生成一边返回 避免一次性返回大量的数据示例1下载大文件deffile_stream(): 大文件分段下载不会爆内存 withopen(bigfile.zip,rb)asf:whilechunk:f.read(1024*1024):yieldchunkrouter.get(/stream-file)defstream_file():returnStreamingResponse(file_stream())示例2模拟ai流式响应defai_stream():forwordin[Hello,FastAPI,Streaming]:yield(word ).encode(utf-8)time.sleep(0.5)router.get(/ai)defai():returnStreamingResponse(ai_stream())6. RedirectResponseRedirectResponse 用于让接口返回一个重定向指令使客户端自动跳转到另一个 URL。基础用法router.get(/login)deflogin():# 登录成功后跳转到首页returnRedirectResponse(url/home)7. response_modelresponse_model用来定义接口“返回数据的结构”FastAPI 会自动做过滤 校验 文档生成。基础用法定义接口和模型对象classUser(BaseModel):name:strage:introuter.get(/user,response_modelUser)# 最终返回的数据必须“符合 User 模型结构”defget_user():return{name:Tom,age:18,password:secret# 会被自动过滤掉}测试一下对于 FastAPI 中请求与响应的基础内容我们就先介绍到这里。关于更多 深入 FastAPI 的内容我们下期再见。