FastAPI 中的依赖注入

前言

依赖注入(DI)是一种编程技术,用于增强代码的可重用性,并促进类与其依赖项之间的解耦。在FastAPI 的上下文中,依赖注入在优化应用程序的灵活性、可测试性和整体架构方面发挥着关键作用。

在 FastAPI 中实现依赖注入

FastAPI 提供了 Depends 函数来声明依赖项。让我们来看一些常用的用例。

基本依赖注入

一个简单的依赖注入示例是注入一个返回消息的函数

import uvicorn
from fastapi import FastAPI, Depends
from starlette.responses import JSONResponse

app = FastAPI()


def get_message():
    return "Hello from Dependency!"


@app.get("/message")
def read_message(message: str = Depends(get_message)):
    return JSONResponse({"message": message})


if __name__ == '__main__':
    uvicorn.run(app="main:app", port=8000)

在这个例子中:

  • get_message() 是一个依赖项。
  • Depends(get_message):将其返回值注入到 read_message 函数中

在这里插入图片描述

FastAPI 中的依赖注入方法

  • 在 FastAPI 中 使用 Depends 函数
  • 在 FastAPI 中处理子依赖项

FastAPI 中 的 Depends 函数

在 FastAPI 中, Depends 函数用于管理依赖注入,作为其他函数的通用参数。这使得 FastAPI 能够有序地处理依赖项,便于在应用程序的不同部分管理和注入所需的组件。

语法

  • @app.get("URL"):指定该函数响应指定 URL 的 HTTP GET 请求的装饰器。
  • def main_function(value: str, list=Depends(dependency_function))
    • value:依赖主函数的字符串参数。
    • list:依赖于 dependency_function 的结果。Depends 函数通常用于处理依赖项并动态获取值。
@app.get("URL")
def main_function(value: str, list=Depends(dependency_function)):
    pass

代码定义了一个 FastAPI 应用程序,其中包含一个水果列表(main_fruits_list)。/fruits/ 端点接受一个查询参数(fruit),并将其添加到主水果列表中,返回一条表示添加成功的消息。水果列表通过依赖项(call_main_fruits) 进行管理。

import uvicorn
from fastapi import FastAPI, Depends

app = FastAPI()

# 创建水果列表
main_fruits_list = ["Apple"]


# 调用主水果列表
def call_main_fruits():
    return main_fruits_list


# 使用 Pydantic 调用主 FastAPI 应用程序
@app.get("/fruits/")
def test_main_fruits(fruit: str, list=Depends(call_main_fruits)):
    list.append(fruit)
    print(list)
    return {"message": f"Added fruit {fruit} in the list"}


if __name__ == '__main__':
    uvicorn.run(app="main:app", port=8000)

在这里插入图片描述

在 FastAPI 中 处理子依赖项

在 FastAPI 中,管理子依赖项涉及组织和处理应用程序中的附加依赖项。这使得在 FastAPI 中引入和使用二级组件或服务的方式更加有条理,有助于构建模块化且易于维护的代码库。

语法

dependency_function 是一个异步函数,依赖于 sub_dependency_function 的结果,并接受一个可选的整数参数 value

async def dependency_function(value: int = Depends(sub_dependency_function)):
    pass
import uvicorn
from fastapi import FastAPI, Depends

app = FastAPI()


# 创建价格的子依赖项
async def sub_dependency_price(price: int):
    if price == 0:
        return 50
    else:
        return price


# 创建水果的依赖项
async def dependency_fruits(fruit: str, price: int = Depends(sub_dependency_price)):
    return {"Fruit": fruit, "Price": price}


# 使用 Pydantic 调用 FastAPI 应用程序
@app.get("/fruits")
async def fetch_authors(fruits_list: dict = Depends(dependency_fruits)):
    return fruits_list


if __name__ == '__main__':
    uvicorn.run(app="main:app", port=8000)

在这里插入图片描述

依赖注入案例

下面是一个使用依赖注入的实际案例。我们将构建一个 用户管理 API,其中包括:数据库访问

数据库依赖注入

我们将使用 SQLAlchemy 来管理数据库会话,并通过依赖注入来使用它们。

安装所需要的包:

pip install fastapi uvicorn sqlalchemy psycopg2 pydantic bcrypt pyjwt python-multipart

我们将使用 SQLAlchemy 来管理数据库会话,并通过依赖注入来使用它们。

**database.py ** 文件

from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker, declarative_base, Session

DATABASE_URL = "mysql+pymysql://root:123456@localhost/fastapi"

engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()


def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()


class User(Base):
    __tablename__ = "users"
    id = Column(Integer, primary_key=True, index=True)
    username = Column(String, unique=True, index=True)
    hashed_password = Column(String)
  • get_db() 是一个提供数据库会话的依赖项
  • yield 语句确保会话在使用后被关闭

创建一个 AuthService 类,使用 JWT 处理认证逻辑(可注入依赖项

auth.py 文件

import jwt
from passlib.context import CryptContext
from datetime import datetime, timedelta

SECRET_KEY = "supersecret"
ALGORITHM = "HS256"
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")


class AuthService:

    @staticmethod
    def hash_password(password: str) -> str:
        return pwd_context.hash(password)

    @staticmethod
    def verify_password(password: str, hashed_password: str) -> bool:
        return pwd_context.verify(password, hashed_password)

    @staticmethod
    def create_jwt_token(user_id: int):
        expiration = datetime.utcnow() + timedelta(hours=1)
        return jwt.encode({"sub": user_id, "exp": expiration}, SECRET_KEY, algorithm=ALGORITHM)


def get_auth_service():
    return AuthService()
  • AuthService 是一个基于 类的依赖项
  • get_auth_service() 是一个可注入的依赖项函数

在 API 路由中注入依赖项

main.py 文件

import uvicorn
from fastapi import FastAPI, Depends, HTTPException, Form
from sqlalchemy.orm import Session
from auth import get_auth_service, AuthService
from database import get_db, User

app = FastAPI()


@app.post("/register")
def register_user(username: str = Form(...), password: str = Form(...), db: Session = Depends(get_db),
                  auth_service: AuthService = Depends(get_auth_service)):
    hashed_password = auth_service.hash_password(password)
    user = User(username=username, hashed_password=hashed_password)
    db.add(user)
    db.commit()
    db.refresh(user)
    return {"message": "User registered successfully"}


@app.post("/login")
def login_user(username: str = Form(...), password: str = Form(...), db: Session = Depends(get_db),
               auth_service: AuthService = Depends(get_auth_service)):
    user = db.query(User).filter(User.username == username).first()
    if not user or not auth_service.verify_password(password, user.hashed_password):
        raise HTTPException(status_code=400, detail="Invalid credentials")
    token = auth_service.create_jwt_token(user.id)
    return {"access_token": token, "token_type": "bearer"}


if __name__ == '__main__':
    uvicorn.run(app="main:app", port=8000)

在这里插入图片描述
在这里插入图片描述

总结

FastAPI 中的依赖注入是一种强大的机制,能够增强代码的模块化和可维护性。通过高效地管理和注入依赖项,FastAPI 让开发人员能够创建更加有条理、可扩展且可测试的应用程序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值