3

我试图弄清楚如何使配置/单例可用于不同的模块。也许有一种我还不知道的标准 Python 方法。所以我创建了一个包含所有应用程序配置的配置单例,并希望与所有模块“共享”它。相同的用例将适用于共享数据库连接。

主文件

app = FastApi()
config = some_config_object_from_somewhere()

app.include_router(
        collection.router,
        prefix='/api/collection'
    )

api/collection.py

router = APIRouter()
@router.post("/", status_code=201)
async def collect():
    # I want to use config that is created/defined in main.py
    # HOW?  I thought dependency injection that is built into FastAPI would
    # help, but can't seem to define something in a different module and have it
    # available in the 'router' module
4

2 回答 2

1

一般来说,关于项目结构,FastAPI 应用程序的基本结构与 Flask 应用程序相同,请参见此处

是时候开始编码了!创建 flaskr 目录并添加__init__.py文件。有__init__.py双重职责:它将包含应用程序工厂,并告诉 Python flaskr 目录应该被视为一个包

FastAPI(以及 Flask 和其他函数式框架)根据使用会话的函数定义数据库访问,请参见此处

在该文档页面下方:

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


@app.post("/users/", response_model=schemas.User)
def create_user(user: schemas.UserCreate, db: Session = Depends(get_db)):  # <<< injected here
    db_user = crud.get_user_by_email(db, email=user.email)
    if db_user:
        raise HTTPException(status_code=400, detail="Email already registered")
    return crud.create_user(db=db, user=user)
于 2020-03-24T16:01:17.883 回答
0

根据@tiangolo(FastAPI 的创建者)的说法:

“您可以在路由器或装饰器级别声明相同的依赖项,然后在路径操作中再次声明它以获取其值。

它不会被评估两次,它不会添加任何额外的计算,存在一个依赖缓存,用于存储给定请求的已解决依赖项的值

https://github.com/tiangolo/fastapi/issues/424#issuecomment-584169213

因此,对于共享数据库连接的情况,您只需get_db在路由器文件中重新导入并重新声明即可。

然而,对于共享配置数据的情况,FastAPI 文档指出依赖项是针对“共享逻辑”、共享“数据库连接”和执行“安全、身份验证、角色要求”——这似乎与共享数据不同。

将您的配置数据放入它自己的模块中就可以完成这项工作(不需要作为单例实现)并且是正式的 Pythonic:

在单个程序中跨模块共享信息的规范方法是创建一个特殊模块(通常称为 config 或 cfg)。只需在应用程序的所有模块中导入配置模块;然后该模块可作为全局名称使用。因为每个模块只有一个实例,所以对模块对象所做的任何更改都会在各处反映出来。

https://docs.python.org/3/faq/programming.html#how-do-i-share-global-variables-across-modules

(单例模式可以说不那么 Pythonic。)

于 2021-07-05T19:13:30.050 回答