PydanticPydantic 是 Fastapi 的核心依赖用于数据校验和序列化。通过使用Python类型注解定义数据结构它负责自动完成数据校验和转换。通过继承BaseModel类来定义一个Pydantic模型字段是否必填取决于是否有默认值没有默认值的字段为必填。常用函数Pydantic模型序列化为字典item.model_dump()【item为pydantic模型实例】Pydantic模型序列化为 jsonitem.model_dump_json()【item为pydantic模型实例】从字典创建Pydantic模型并自动校验User.model_validate(user_dict)from pydanticimportBaseModel, EmailStr class User(BaseModel): name: str age: int email: EmailStr# 这是 Python 字典user_dict{name:小明,age:20,email:testqq.com}# 字典 → 模型 自动校验userUser.model_validate(user_dict)从 json 创建Pydantic模型并自动校验User.model_validate_json(json_str)# 这是 JSON 字符串json_str{name:小红,age:18,email:testqq.com}# JSON字符串 → 模型 自动校验userUser.model_validate_json(json_str)模型配置 ——作用控制模型行为一、最常用模型配置frompydanticimportBaseModel,ConfigDictclassUser(BaseModel):name:strage:intmodel_configConfigDict(# 1. 允许从 ORM 对象读取数据必用from_attributesTrue,# 2. 禁止额外字段安全必开extraforbid,# 3. 字符串自动去除空格必用str_strip_whitespaceTrue,# 4. 支持别名驼峰/下划线互转populate_by_nameTrue,# 5. 宽松类型转换更友好coerce_numbersTrue,# 6. 自定义 API 文档示例json_schema_extra{example:{name:张三,age:20}},# 7. 时间格式统一ser_json_tzFalse,# 8. 枚举使用值而不是名称use_enum_valuesTrue)二、每个参数作用 为什么要用1.from_attributes True最最最重要作用让模型支持从ORM 模型数据库对象直接转换为什么企业用数据库查出来的对象一行代码转成接口返回模型userUser.model_validate(db_user)2.extra “forbid”安全必开作用拒绝多余字段前端多传乱七八糟的字段 → 直接报错为什么企业用防止脏数据、防止攻击、保证接口严格规范可选值forbid→ 禁止额外字段推荐ignore→ 忽略allow→ 允许不推荐3.str_strip_whitespace True作用字符串自动去空格 张三 → 张三为什么企业用用户输入经常带空格统一处理避免bug4.populate_by_name True作用支持字段别名比如模型字段user_id接收userId为什么企业用前端用驼峰后端用下划线自动兼容5.coerce_numbers True作用自动类型转换18 → 1820.5 → 20.5为什么企业用前端传字符串数字后端自动转 int/float不报错6.json_schema_extra作用给 API 文档加示例为什么企业用前端看文档一目了然7.use_enum_values True作用枚举返回值而不是枚举名称# 枚举classStatus(str,Enum):SUCCESSsuccess# 开启后返回 success不返回 Status.SUCCESS为什么企业用接口返回干净、规范8.ser_json_tz False作用时间不自动加时区为什么企业用避免前端时间错乱三、企业级万能通用模型基类真实企业项目都会写一个BaseModel让所有模型继承frompydanticimportBaseModelasPydanticBaseModelclassBaseModel(PydanticBaseModel):model_config{from_attributes:True,extra:forbid,str_strip_whitespace:True,populate_by_name:True,coerce_numbers:True,use_enum_values:True}以后所有模型直接继承classUser(BaseModel):name:strage:int✅ 自动拥有全部企业级配置四、一句话总结model_config 不是给文档看示例的是控制模型行为、保证安全、规范、稳定的核心配置Fastapi 响应数据Fastapi 响应数据都会自动将返回结果转换成json 格式发送给客户端给人看的。也就是不管你路由函数返回的是字典还是Pydantic模型实例都会自动转换成json格式。依赖注入依赖注入一种设计模式让你可以将通用的逻辑如数据库连接、身份验证、参数校验等提取为可复用的组件然后在路由中按需使用。Fastapi会在执行路由函数之前自动调用依赖函数并将返回值传递给路由函数。依赖函数和路径操作函数使用相同的参数声明方式FastAPI 会自动解析依赖函数的参数。这意味着依赖函数也可以使用查询参数、路径参数、请求体等。依赖函数里可以直接写查询参数 q: str路径参数 user_id: int请求头 token: str Header()Cookie session_id: str Cookie()请求体模型 user: User甚至其他依赖FastAPI 全部自动解析。类作为依赖使用类作为依赖class CommonQueryParams: def __init__(self, q: str|NoneNone, skip: int0, limit: int100): self.qq self.skipskip self.limitlimit# 使用类作为依赖app.get(/items/)async def read_items(commons: Annotated[CommonQueryParams, Depends()]):return{q:commons.q,skip:commons.skip,limit:commons.limit}Annotated 是 Python 官方语法3.9作用给类型加 “附加信息”格式Annotated[类型, 附加信息1, 附加信息2...]Depends() 是什么平时我们写依赖是Depends(函数名)但这里是类不是函数所以 FastAPI 允许你简写Depends()# 自动用前面的类作为依赖下面两种写法功能完全一样写法 A你给的优雅async def read_items(commons: Annotated[CommonQueryParams, Depends()]):写法 B原始写法啰嗦async def read_items(commons: CommonQueryParamsDepends()):为什么要用 Annotated好处是什么类型更干净不用写 Depends() 在后面官方推荐风格可以放多个依赖 / 元数据Annotated[User, Depends(get_user), Depends(check_token)]代码更统一、更优雅类作为依赖同时使用多个的正确写法一个接口想用 A 类依赖 B 类依赖两个都要怎么写一、先准备两个类依赖示例fromtypingimportAnnotatedfromfastapiimportDepends,FastAPI appFastAPI()# 类依赖 1公共查询参数classCommonParams:def__init__(self,q:str|NoneNone,skip:int0,limit:int10):self.qq self.skipskip self.limitlimit# 类依赖 2鉴权比如 token 校验classAuthCheck:def__init__(self,token:strdefault):self.tokentokenifself.token!valid:raiseException(无效token)二、同时使用多个类依赖的 3 种写法任选写法 1最标准、最推荐Annotatedapp.get(/items)asyncdefget_items(# 第一个类依赖params:Annotated[CommonParams,Depends()],# 第二个类依赖auth:Annotated[AuthCheck,Depends()]):return{q:params.q,skip:params.skip,token:auth.token}✅直接写多个参数每个都是一个类依赖写法 2老式写法不用 Annotatedapp.get(/items)asyncdefget_items(params:CommonParamsDepends(),auth:AuthCheckDepends()):return{q:params.q,token:auth.token}✅ 和上面功能完全一样只是写法旧一点写法 3在装饰器里批量注入不需要返回值时app.get(/items,dependencies[Depends(AuthCheck),Depends(CommonParams)])asyncdefget_items():return{msg:同时通过了两个类依赖校验}✅适合只做校验不需要拿到返回值的场景如鉴权、日志、限流三、一句话终极总结多个类依赖 函数参数里写多个每个都用 Annotated 或 Depends()就像这样asyncdef接口(依赖1:Annotated[类1,Depends()],依赖2:Annotated[类2,Depends()]):四、总结我再给你一句最精简的类依赖想写多少个就写多少个和函数参数一样直接并列写就行什么叫「对整个路由组使用依赖」这里会学习一个新的词汇路由组以及学习如何优雅的给一组路由设置依赖一句话给一组接口一次性加上同一个依赖不用每个接口都重复写。就像给整个班级设置门禁不是给每个学生单独设置。一、先看你这段代码# 依赖校验 API Keyasyncdefverify_api_key(x_api_key:strHeader()):ifx_api_key!secret-key:raiseHTTPException(...)你给两个接口都加了依赖app.get(/items/,dependencies[Depends(verify_api_key)])app.get(/users/,dependencies[Depends(verify_api_key)])这就是每个接口自己带依赖重复代码二、真正的「路由组 统一依赖」长这样FastAPI 有个东西叫APIRouter路由分组作用把一堆接口归为一组统一加前缀、统一加依赖代码示例一看就懂fromfastapiimportAPIRouter# 1. 创建一个路由组比如叫需要鉴权的接口组routerAPIRouter(prefix/api,# 统一前缀dependencies[Depends(verify_api_key)]# 统一依赖)# 2. 下面所有接口自动带上上面的依赖不用再写router.get(/items)defread_items():return[{item:Foo}]router.get(/users)defread_users():return[{user:Bar}]# 3. 把路由组挂载到 appapp.include_router(router)效果/api/items→ 自动校验 API Key/api/users→ 自动校验 API Key你不用在每个接口上写 dependencies三、终极通俗理解没有路由组每个接口 →自己带钥匙自己写依赖有路由组整个组 →大门统一上锁里面所有接口都受保护四、三种使用依赖的方式必背1. 接口函数内使用拿到返回值defread_items(authDepends(verify_api_key)):2. 装饰器里单独给一个接口用app.get(/items,dependencies[Depends(verify_api_key)])3. 给整个路由组用最常用routerAPIRouter(dependencies[Depends(verify_api_key)])五、一句话总结超级好记路由组 给一堆接口批量设置统一规则前缀、依赖、标签dependencies[…] 给这一组全部自动鉴权你现在懂了吗我再给你一句最精简的给路由组加依赖 批量给一组接口加鉴权/校验不用重复写代码。字典 跟 json 的区别长得很像但完全不是一回事字典 (dict)是Python 内存里的对象给代码用的JSON是纯文本字符串给网络/文件用的直观对比1. Python 字典代码里的# 这是 Python 对象运行在内存里person{name:小明,age:20,is_student:True,# 大写 Thobby:None# None 表示空}特点引号单双引号都行布尔值True/False大写空值None可以存函数、对象、日期等复杂内容2. JSON文本字符串{name:小明,age:20,is_student:true,# 小写 thobby:null#null}特点只能用双引号绝对不能用单引号布尔值true/false小写空值null只能是纯文本不能存函数/对象核心区别特性Python 字典 (dict)JSON本质内存数据结构纯文本字符串引号单/双引号都可以必须双引号布尔值TrueFalsetruefalse空值Nonenull用途代码里存数据网络传输、存文件注释支持不支持它们的关系转换Python 提供了json库帮你互相转换字典 → JSON序列化importjson# 字典person{name:小明,age:20}# 转成 JSON 字符串json_strjson.dumps(person)print(type(json_str))# class str 变成文本了JSON → 字典反序列化# JSON 字符串json_str{name: 小明, age: 20}# 转成字典personjson.loads(json_str)print(type(person))# class dict 变回代码对象最简单的理解字典 你脑子里想的信息JSON 写在纸上、发给别人的文字你要把想法传给别人必须写下来转 JSON别人收到文字要理解必须变成想法转字典请求头和 Cookie是什么一、请求头 Request Headers浏览器/客户端发请求时附带的附加信息包放在请求报文头部服务端用来识别、校验、适配请求。常见作用告诉服务器客户端类型、浏览器、系统携带认证令牌、权限标识声明能接收的数据格式、编码跨域、防盗链校验常用字段User-Agent客户端设备与浏览器信息Content-Type请求体数据格式JSON/表单Authorization登录令牌鉴权Referer来源页面地址二、Cookie服务器下发、存在浏览器本地的小型文本数据跟随每次请求自动带回服务端。核心用途记录登录状态维持会话保存用户偏好、临时标识识别同一访客身份特点大小有限只存简单字符串可设置过期时间每次同源请求自动携带发送三者关系直白类比请求体真正要提交的业务数据表单、参数请求头附带说明、身份凭证、格式说明Cookie随身身份小卡片自动跟着请求走一句话区分请求头是通用附加说明Cookie是存本地、自动携带的身份小数据。请求头和cookie在fastapi中的作用以及使用场景有哪些一、先记住一句话请求头 快递单上的所有信息Cookie 快递单里的「身份贴条」在 FastAPI 里请求头用来识别、鉴权、控制请求Cookie用来记住用户、保持登录状态二、请求头 Header 在 FastAPI 里的作用作用传递身份凭证token告诉接口数据格式做权限校验做跨域、防盗链、设备识别FastAPI 中怎么用1. 获取请求头fromfastapiimportFastAPI,Header appFastAPI()app.get(/)defread_root(user_agent:strHeader()):return{你的浏览器信息:user_agent}2. 最常用场景从请求头拿 Token 登录鉴权app.get(/user/info)defuser_info(authorization:strHeader()):# 校验 token 是否正确ifauthorization!Bearer 123456:return{msg:未登录}return{msg:已登录欢迎回来}请求头使用场景登录鉴权最常用接口版本控制传递语言、时区客户端设备判断接口限流、权限控制三、Cookie 在 FastAPI 里的作用作用自动记住用户不用每次都传 token保持登录状态存储少量用户信息识别访客FastAPI 中怎么用1. 获取 CookiefromfastapiimportCookieapp.get(/get-cookie)defget_cookie(session_id:str|NoneCookie(None)):return{你的会话ID:session_id}2. 设置 Cookie登录成功后下发fromfastapiimportResponseapp.get(/login)deflogin(response:Response):# 给浏览器设置 cookieresponse.set_cookie(keysession_id,valueabc123def)return{msg:登录成功cookie已下发}Cookie 使用场景网站登录状态保持记住我7天免登录购物车、用户偏好会话识别后台管理系统登录四、最关键区别面试必考请求头 Header手动传适合接口、APP、小程序更安全、更灵活前后端分离首选Cookie浏览器自动传适合网站、网页自动维持登录传统 Web 项目用得多五、FastAPI 开发中最真实的使用场景1. 90% 前后端分离项目请求头 TokenAuthorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...2. 管理后台、网页项目Cookie Session登录成功 → 下发 Cookie下次访问 → 浏览器自动带上FastAPI 直接读取判断是否登录3. 文件下载、接口加密请求头带签名、时间戳等。4. 多语言接口请求头带Accept-Language返回对应语言。六、超级简单总结请求头 Header作用鉴权、传附加信息、控制请求场景登录 token、版本、设备、格式特点手动传前后端分离主流Cookie作用记住用户、保持登录场景网站登录、购物车、会话特点浏览器自动带适合网页自定义响应头有什么作用以及应用场景是一、什么是自定义响应头就是服务器在返回数据时额外塞给客户端的一段“小信息”。它不在返回的 JSON 里而是藏在响应的头部。客户端浏览器/前端可以拿到但用户看不见。二、自定义响应头有什么用核心作用传递额外信息不污染业务数据不想把状态、版本、提示放进 JSON就放响应头。控制前端行为让浏览器缓存、跨域、不缓存、重定向等。安全控制防劫持、防XSS、防盗链。接口监控、调试、日志传请求ID、处理时间、服务版本。权限/状态标记告诉前端是否需要刷新登录、限流等。三、最常用的应用场景真实开发 90% 都会用到1. 跨域配置最最常用Access-Control-Allow-Origin: *允许前端调用接口解决跨域报错。2. 禁止缓存 / 强制刷新Cache-Control: no-cache让浏览器每次都拿最新数据不读本地缓存。登录接口、支付接口、实时数据必用3. 传递接口处理时间、请求唯一ID日志排查X-Process-Time: 0.032 X-Request-ID: abc123def456方便查问题哪个请求慢哪次调用出错4. 安全防护必加X-Content-Type-Options: nosniff X-XSS-Protection: 1防止网页被劫持、XSS攻击。5. 告诉前端Token 快过期了需要刷新X-Token-Expire-Soon: true前端自动跳登录或刷新token。6. 接口版本控制X-API-Version: 2.0区分新旧接口。7. 文件下载时告诉浏览器文件名Content-Disposition: attachment; filenamereport.pdf8. 限流提示X-RateLimit-Remaining: 5告诉用户还能调用几次接口。四、FastAPI 中如何自定义响应头直接复制用方式1单个接口返回自定义头fromfastapiimportFastAPI,Response appFastAPI()app.get(/api/data)defget_data(response:Response):# 自定义响应头response.headers[X-Process-Time]0.025response.headers[X-API-Version]2.0response.headers[Cache-Control]no-cachereturn{msg:数据返回成功}方式2全局统一加响应头所有接口都带fromfastapiimportFastAPI,Request,Responsefromfastapi.responsesimportJSONResponse appFastAPI()app.middleware(http)asyncdefadd_custom_header(request:Request,call_next):responseawaitcall_next(request)# 统一给所有接口加响应头response.headers[X-Server]FastAPI-Serverresponse.headers[X-Env]Productionreturnresponse五、一句话记住自定义响应头不污染返回数据又能给前端传秘密信息、控制行为、加强安全、方便调试。它是后端和前端之间的悄悄话通道。六、最简单总结必背自定义响应头的作用传额外信息控制浏览器/前端行为加强安全方便调试、日志、监控使用场景跨域缓存控制请求ID、耗时安全防护Token 过期提醒接口版本文件下载