96SEO 2026-08-08 15:27 0
在FastAPI后端开发里依赖注入是最主要、也最容易被低估的能力之一。很多开发者习惯在每个路由函数里重复写鉴权、打日志、开数据库连接、解密参数。导致接口越来越胖,改动一处需要遍历多处,单元测试几乎无从下手。怎么说呢,FastAPI的Depends机制正是为了解决这些横切关注点。把它们从业务逻辑里剥离出来。
先看一种常见的写法:每个接口都自己从request里抠分页参数、自己校验Token,业务代码被挤到函数末尾。

@app.get
async def list_users:
page = int)
page_size = int)
token = request.headers.get.replace
if token not in VALID_TOKENS:
raise HTTPException
# 业务逻辑从这里才开始…,
问题在于的观点是。分页和鉴权与列出使用者毫无关系,却在每个路由里复制粘贴。依赖注入的改法是把解析分页和当前使用者各自写成独立函数,路由参数里用Depends声明需求即可。
@app.get
async def list_users(
pagination: Pagination = Depends,user: UserInfo = Depends,):
# pagination 和 user 已经就绪。直接写业务
...
FastAPI看到Depends时会先调用get_pagination并把返回值赋给pagination再进入路由函数体。路由函数不再碰Request的原始字段,签名本身也变成了文档:一眼能看出该接口需要分页信息和登录使用者。不过,
任何可调用对象都可以当依赖,最常用的是普通函数。下面这个get_pagination把分页规则集中在一处:page默认1且不小于1,page_size默认10、范围1~100,并顺带算出SQL常用的offset.
def get_pagination(
至于page。int = Query,page_size: int = Query,) -> Pagination:
return Pagination(
page=page,page_size=page_size,offset= * page_size,)
痛点嵌入: 如果没有依赖注入,这段分页校验必须在每个路由里手动写;一旦业务要求改动,所有地方都要同步修改,极易漏掉。
注意: 依赖函数参数上的Query不是路由函数的参数,却会被FastAPI一样解析。说白了谁声明Depends,谁就自动拥有 ?page=&page_size= 两个查询参数,而且 Swagger 会展示来无需额外配置。
路由侧只需一行声明:
@app.get
async def demo_basic_dep(
pagination: Pagination = Depends,request_id: str = Depends,):
return {"pagination": pagination.model_dump。"request_id": request_id}
Pain point: 在没有统一 X-Request-ID 处理时每次排查故障只能靠日志时间戳,对齐困难;使用下面的依赖后即使前端不传,也会自动生成 UUID,实现全链路追踪。
P.S. get_request_id 示例实现略去,仅展示其作用。
有时依赖本身需要构造参数——比如 A 接口 30 秒内最多 3 次B 接口 60 秒内最多 100 次。
把限流写成一个类,实现 __call__。实例即可当作依赖使用:
class RateLimiter: def __init__: self.max_calls = max_calls self.window_seconds = window_seconds self._calls: list = def __call__ -> None: now = time.time # 清掉滑动窗口外的旧记录 self._calls = if="" len="">= self.max_calls: raise HTTPException self._calls.append
Pain point: 如果用装饰器实现限流,需要在每个视图上显式写装饰器且管理全局状态;类依赖让限流策略可以像普通对象一样配置并复用。
Create two configured instances:
rate_limit_strict = RateLimiter rate_limit_loose = RateLimiter
The router simply mounts dependency:
@app.get async def demo_class_dep): return {"message": "限流通过"}
The underscore placeholder signals that we only care about side‑effect。not return value.
A typical auntication flow is built as a chain of dependencies. FastAPI will resolve m top‑down and cache results within a single request.
bearer_scheme = HTTPBearer def get_token( credentials: HTTPAuthorizationCredentials | None = Depends,) -> str: if credentials is None or credentials.scheme.lower!= "bearer": raise HTTPException return credentials.credentials def verify_token) -> int: user_id = _TOKENS.get if user_id is None: raise HTTPException return user_id def get_current_user) -> UserInfo: row = _DB.get if row is None: raise HTTPException return UserInfo def require_admin) -> UserInfo: if user.role!= "admin": raise HTTPException return user
Pain point: 在 Flask 中往往把所有检查塞进同一个装饰器或全局变量。一旦需求变化,必须修改所有视图;而子依赖让每一步职责单一,可独立替换或复用。
A route that only needs a normal logged‑in user:
@app.get async def demo_sub_dep): return user
The granularity of dependency registration determines its scope:
Main FastAPI;applies to every endpoint.async def global_request_timer -> None: request.state.start_time = time.perf_counter app = FastAPI])
secure_router = APIRouter( prefix="/secure",dependencies=,) @secure_router.get async def secure_profile): return user @secure_router.get async def admin_stats): return {"admin": admin.username,"user_count": len} app.include_router
If a dependency is declared multiple times within one request,FastAPI executes it **once** and reuses result.
_call_counter={"expensive_sync":0} def expensive_sync_service -> dict: _call_counter += 1 return {"engine":"sync","calls_in_request":_call_counter} @app.get async def demo_cache( a: dict = Depends,b: dict = Depends,c: dict = Depends,): return {"cached_twice":a,"cached_again":b,"no_cache":c}
The first two parameters share same cached result . The third forces re‑execution . This behavior eliminates redundant DB lookups or token checks.
async def expensive_async_service -> dict: await asyncio.sleep return {"engine":"async"}
@contextmanager def get_db_session: session={"data":_DB} 从try来看。yield session finally: session.clear @asynccontextmanager async def get_async_db_session: session={"data":_DB} try的观点是,await asyncio.sleep # 模拟获取连接池连接 yield session finally: session.clear
The chain from previous “子依赖” section becomes canonical auntication solution. Normal endpoints use
async def log_request( request: Request,request_id: str = Depends,) -> None: _REQUEST_LOGS.append({ "request_id": request_id,"method": request.method,"path": request.url.path,"client": request.client.host if request.client else "unknown","at": datetime.now.isoformat,})
This dependency can be attached globally or per‑router. Because it lives in a dependency tree rar than inline code,developers never forget to add logging statements when y create new routes – a common source of operational blind spots in Flask projects.
If front‑end encrypts sensitive fields,each view would orwise need its own decryption logic. Wrap it into a dependency:
def _decode_encrypted_note->str|None: if value is None:return None try的观点是,return base64.b64decode).decode except Exception as exc: raise HTTPException from exc def decrypt_order_body -> DecryptedOrderCreate: return DecryptedOrderCreate( product=body.product,amount=body.amount,note=_decode_encrypted_note,) @app.post async def demo_decrypt_order): return order
def get_user_repo): # 假设 session 是一个简易字典型仓库 return session @app.get async def demo_db_session( repo=Depends,pagination: Pagination = Depends,): users=list) start,p_end=pagination.offset,pagination.offset+pagination.page_size return {"total":len。"items":users}
This three‑layer design guarantees that connection lifetimes are managed by dependencies alone—no risk of forgetting
在 Flask 中通常这样实现登录检查:
" language -python "> def loginrequired: @wraps def decorated: token=request.headers .get if not verify: ret urn jsonify,401 g .currentuser=get_user ret urn f ret urn decorated
@app.route
@login_required
def profile:
ret urn jsonify
主要理念 : 把「拿到对象」这件事抽成独立可复用的 **dependency**,而把「业务规则」留给路由函数本身。这样可以做到的观点是,ul> li>函数级别 : 分页、Header解析等无状态工具直接写成普通函数。li>类级别 : 带构造参数的策略封装为可实例化对象。li>子依赖链 : Token 校验 → 使用者加载 → 权限判断。各环节职责单一,可自由组合。li>全局/Router 级挂载 : 横切关注点一次声明,全站生效或按模块划分。li>默认缓存 : 同一次请求内部不会重复执行昂贵操作。li>异步 & yield : 完美支持异步 IO 与资源释放。ul> Li>
Pain point 回顾 : 当你仍然在每个视图里手动抄代码时你会面对: ul> Li>
FastAPI 的 Depends 正好解决了以上全部痛点,让代码更干净、更安全、更易测。
Li>
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback