我也可以将 MongoDB 与 FastAPI 一起使用
但是,我也想使用fastapi-users,因为它可以很好地与开箱即用的 MongoDB 配合使用。缺点是它似乎只适用于处理我的数据库客户端连接(即全局)的第一种方法。原因是为了配置 fastapi-users,我必须有一个活动的 MongoDB 客户端连接,这样我才能制作db
如下所示的对象,然后我需要它db
来制作MongoDBUserDatabase
fastapi-users 所需的对象:
# main.py
app = FastAPI()
# Create global MongoDB connection
DATABASE_URL = "mongodb://user:paspsword@localhost/auth_db"
client = motor.motor_asyncio.AsyncIOMotorClient(DATABASE_URL, uuidRepresentation="standard")
db = client["my_db"]
# Set up fastapi_users
user_db = MongoDBUserDatabase(UserDB, db["users"])
cookie_authentication = CookieAuthentication(secret='lame secret' , lifetime_seconds=3600, name='cookiemonster')
fastapi_users = FastAPIUsers(
user_db,
[cookie_authentication],
User,
UserCreate,
UserUpdate,
UserDB,
)
在代码中的那一点之后,我可以导入 fastapi_users 路由器。但是,如果我想将我的项目分解为我自己的 FastAPI 路由器,我会感到很沮丧,因为:
- 如果我将
client
创建移动到另一个模块以导入到我app
和我的路由器中,那么我在不同的事件循环中有不同的客户端并得到类似的错误RuntimeError: Task <Task pending name='Task-4' coro=<RequestResponseCycle.run_asgi() running at /usr/local/lib/python3.8/site-packages/uvicorn/protocols/http/h11_impl.py:389> cb=[set.discard()]> got Future <Future pending cb=[_chain_future.<locals>._call_check_cancel() at /usr/local/lib/python3.8/asyncio/futures.py:360]> attached to a different loop
(在这个 SO 问题中涉及) - 如果我使用“真实世界示例”的解决方案,那么我会陷入在
fastapi_users
代码示例中构建对象的位置:我不能这样做,main.py
因为还没有db
对象。
我考虑将MongoDBUserDatabase
对象作为startup
事件代码的一部分(即在async def connect_to_mongo()
真实世界示例中),但我也无法让它工作,因为我看不到如何让它工作。
我怎么能
- 以一种可以在我的主要
app
和几个之间共享的方式创建一个全局 MongoDB 客户端和 FastAPI-User 对象,routers
而不会出现“附加到不同的循环”错误,或者 - 创建精美的包装类和函数以使用触发器设置 FastAPI 用户
startup
?