ODMantic

raw JSON →
1.1.0 verified Fri May 01 auth: no python

ODMantic is an async ODM (Object Document Mapper) for MongoDB, based on Pydantic and Motor. It leverages Python type hints to define models and provides a clean asynchronous API. Current version is 1.1.0, with active development and quarterly releases.

pip install odmantic
error AttributeError: 'AIOEngine' object has no attribute 'save'
cause In older versions (<0.7), 'save' was a method on the Engine instance. After refactoring, it's still a method, but the error may occur if a typo or using a wrong object.
fix
Ensure you're using the AIOEngine correctly: await engine.save(instance). Verify you have installed ODMantic >=0.7.
error pydantic.errors.PydanticUserError: Cannot use `Field` from pydantic inside an ODMantic model
cause Using `from pydantic import Field` instead of `from odmantic import Field`.
fix
Change the import to: from odmantic import Field
error TypeError: 'coroutine' object does not support item assignment
cause Forgetting to await an async engine call (e.g., `engine.find_one(...)` returns a coroutine, not the result).
fix
Add await before the engine call: player = await engine.find_one(...)
breaking ODMantic 1.0.0 dropped support for Pydantic v1 and Python 3.7. Models defined with Pydantic v1 syntax will break.
fix Upgrade models to Pydantic v2 syntax (e.g., use `Field` from odmantic, update validators).
gotcha Do not mix ODMantic's `Field` with Pydantic's `Field`. Using `from pydantic import Field` inside an ODMantic model can cause validation issues.
fix Always import Field from odmantic: `from odmantic import Field`.
gotcha ODMantic models are async-only. Calling `save()` without `await` will not persist data and may return a coroutine.
fix Always use `await` with engine methods like `save`, `find`, `find_one`, `delete`, etc.

Creates a Player model, saves an instance to MongoDB, and retrieves it.

import asyncio
from odmantic import AIOEngine, Model, Field
from motor.motor_asyncio import AsyncIOMotorClient

class Player(Model):
    name: str
    level: int = Field(default=1)

async def run():
    client = AsyncIOMotorClient(os.environ.get('MONGODB_URI', 'mongodb://localhost:27017'))
    engine = AIOEngine(motor_client=client, database='test')
    player = Player(name='Alice', level=5)
    await engine.save(player)
    print(f"Saved player with id: {player.id}")
    found = await engine.find_one(Player, Player.name == 'Alice')
    print(found)
    client.close()

asyncio.run(run())