MongoDb с FastAPI
Я немного поигрался с FastAPI и хотел подключить его к базе данных MongoDB. Я, однако, смущен, какой ODM выбрать между двигателем, который является асинхронным и mongoengine. Кроме того, в примере с NoSQL здесь они создали новый сегмент, а также вызываемый код для подключения к БД при каждом его использовании. Тем не менее, как двигатель, так и двигатель, кажется, предпочитают глобальную связь. Так, что было бы хорошим способом соединиться с mongodb?
3 ответа
Я считаю, что вы уже получили ответы на форумах по проблемам проекта Fastapi на Github: Issue 452 (закрыто). Но я резюмирую решения здесь для справок в будущем:
Короче говоря, вы можете использовать либо мотор, либо http://mongoengine.org/, Fastapi поддерживает оба, и вы можете повторно использовать глобальный клиентский объект, который запускается и завершается процессом вашего приложения.
Некоторые детали контекста (надеюсь), чтобы прояснить эти технологии и их отношения:
Официальный драйвер MongoDB для Python - pymongo. Под капотами и MongoEngine, и Motor используют Pymongo. Pymongo реализует прямого клиента для MongoDB (демонов) и предлагает Python API для выполнения запросов.
Если хотите, вы можете использовать pymongo напрямую с Fastapi. (С точки зрения SQL это было бы эквивалентно использованию psycopg2 во Flask напрямую, без использования чего-то вроде SQLAlchemy.)
MongoEngine - это ODM (средство сопоставления объектов и документов). Он предлагает объектно-ориентированный API Python, который вы можете использовать в своем приложении для более комфортной работы, а когда дело доходит до фактических запросов к БД,MongoEngine будет использовать pymongo.
Motor - это оболочка для pymongo, которая делает его неблокирующим (разрешает async / await). Он использует цикл событий либо через Tornado, либо через asyncio. Если вы используете Fastapi с uvicorn, uvicorn будет реализовывать асинхронные функции с помощью uvloop. Короче говоря, используя Motor с FastAPI, async должен "просто работать". К сожалению, в Motor не реализован ODM. В этом смысле он больше похож на пимонго.
Fastapi обрабатывает запросы от клиентов (используя Starlette), но позволит вам реализовать собственное подключение к MongoDB. Таким образом, вы не ограничены каким-либо конкретным выбором, но в основном вы сами (а-ля 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 можно найти здесь.
Недавно я создал Async Mongo ODM, хорошо подходящий для 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
Вы можете взглянуть на пример FastAPI для получения более подробного примера.
Я не согласен с принятым ответом о том, что fastapi является однопоточным. Насколько я могу судить, fastapi является только однопоточным, если вы обрабатываете запросы с помощью асинхронной функции. Поэтому, если вы не используете асинхронность под капотом, Starlette должна использовать несколько потоков из пула потоков для обработки нескольких запросов.
Для получения дополнительной информации о модели потоков и асинхронности в fastapi/starlette это хорошее введение https://fastapi.tiangolo.com/async/