我相信你已经在Github上的Fastapi项目的问题论坛中得到了你的答案:Issue 452 (closed)。但为了以后参考,我会在这里总结解决方案:
简而言之,你可以使用motor或mongoengine,Fastapi都支持,并且你可以重复使用一个全局客户端对象,该对象启动并随应用程序进程结束。
一些上下文细节(希望)澄清这些技术及其关系:
Python的官方MongoDB驱动程序是pymongo。在幕后,MongoEngine和Motor都使用Pymongo。 Pymongo实现了一个针对MongoDB(备件)的直接客户端,并提供了一个Python API来发出请求。
如果您愿意,您可以直接在Fastapi中使用pymongo。(在SQL方面,这相当于在Flask中直接使用psycopg2而无需通过类似SQLAlchemy的东西。)
MongoEngine是一个ODM(对象-文档映射器)。 它提供了一个Python面向对象的API,您可以在应用程序中使用它来更舒适地工作,当涉及到实际的DB请求时,MongoEngine将使用pymongo。
Motor是pymongo的封装,使其非阻塞(允许async/await)。 它使用一个事件循环,通过Tornado或asyncio。 如果您正在使用带有uvicorn的Fastapi,则uvicorn将使用uvloop实现异步功能。 简而言之,在FastAPI中使用Motor,异步应该“只是工作”。 不幸的是,Motor没有实现ODM。 在这个意义上,它更类似于pymongo。
Fastapi处理来自客户端的请求(使用Starlette),但它会让您实现自己对MongoDB的连接。 因此,您并不限于任何特定的选择,但大多数情况下都是自己操作(a la Flask)。
您可以使用FastAPI应用程序的启动/关闭钩子来启动/停止Motor/MongoEngine客户端。 由于Fastapi是单线程的,因此您不需要担心由于多进程问题而导致客户端对象不持久。
@app.on_event("startup")
async def create_db_client():
# start client here and reuse in future requests
@app.on_event("shutdown")
async def shutdown_db_client():
# stop your client here
可以在这里找到使用Fastapi实现电机的示例。
我最近创建了一个适用于FastAPI的异步Mongo ODM:ODMantic。
app = FastAPI()
engine = AIOEngine()
class Tree(Model):
"""This model can be used either as a Pydantic model or
saved to the database"""
name: str
average_size: float
discovery_year: int
@app.get("/trees/", response_model=List[Tree])
async def get_trees():
trees = await engine.find(Tree)
return trees
@app.put("/trees/", response_model=Tree)
async def create_tree(tree: Tree):
await engine.save(tree)
return tree
您可以查看FastAPI示例,以获得更详细的例子。
我不同意接受的答案,认为fastapi是单线程的。
据我所知,如果您使用异步函数处理请求,则fastapi只能是单线程的。因此,如果您在幕后不使用异步,则starlette应该使用来自线程池的多个线程来处理多个请求。
有关线程模型和fastapi / starlette中的异步的更多信息,请参见此介绍https://fastapi.tiangolo.com/async/。