MongoDb with FastAPI
I believe you already got your answers in the issue forums of the Fastapi project on Github: Issue 452 (closed). But I'll recap the solutions here for future reference:
In short, you can use either motor or mongoengine, Fastapi supports both and you can reuse a global client object that's started and ended with your app process.
Some context details to (hopefully) clarify these technologies and their relationships:
The official MongoDB driver for Python is pymongo. Under the hoods, both MongoEngine and Motor use Pymongo. Pymongo implements a direct client for MongoDB (daemons) and offers a Python API to make requests.
If you wanted to, you could use pymongo with Fastapi directly. (On th SQL side of things, this would be equivalent to using psycopg2 in Flask directly without going through something like SQLAlchemy.)
MongoEngine is an ODM (Object-Document Mapper). It offers a Python object-oriented API that you can use in your application to work more comfortably and when it comes to the actual DB requests, MongoEngine will use pymongo.
Motor is a wrapper for pymongo that makes it non-blocking (allowing async/await). It uses an event-loop, either through Tornado or through asyncio. If you are using Fastapi with uvicorn, uvicorn will implement async functionality with uvloop. In short, using Motor with FastAPI, async should "just work". Unfortunately, Motor does not implement an ODM. In this sense it is more similar to pymongo.
Fastapi handles the requests from clients (using Starlette), but it will let you implement your own connection to MongoDB. So you are not restricted to any particular choice, but you are mostly on your own (a la Flask).
You can use the startup/shutdown hooks of your FastAPI app to start/stop your Motor/MongoEngine client. You don't need to worry about your client object not persisting due to multiprocess issues, because Fastapi is single-threaded.
@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
An example implementation of motor with Fastapi can be found here.
I recently created an Async Mongo ODM well suited for FastAPI: 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
You can have a look to the FastAPI example for a more detailed example.