Getting Started¶
Installation¶
NextORM requires Python 3.12 or later. Install the base package plus the driver for your database:
pip install nextorm[sqlite]
pip install nextorm[postgres]
pip install nextorm[mariadb]
pip install "nextorm[sqlite,postgres,mariadb]"
Quick start¶
The minimal setup is:
Define entity classes that inherit from
Entity.Call
generate_mapping()to wire entities to database tables.Wrap all data access in a
db_session()context.
from nextorm import Database, Entity, PK, Req, Opt, db_session
# Step 1 — define entities
class User(Entity):
id: PK[int]
name: Req[str]
email: Req[str]
age: Opt[int]
# Step 2 — create and bind a database
db = Database(entities=[User])
db.bind("sqlite", "app.db")
# Step 3 — create tables (dev/test only; use migrations in production)
db.generate_mapping(create_tables=True)
# Step 4 — work inside a session
with db_session:
user = User(name="Alice", email="alice@example.com", age=30)
# ← INSERT fires automatically on commit; user.id is now set
# Querying — using the class-level shortcut (no explicit db reference needed)
users = User.select().filter(User.age >= 18).fetch_all()
alice = User.get(email="alice@example.com") # None if not found
user = User[1] # KeyError if not found
First steps with async¶
For async applications swap AsyncDatabase and
use await everywhere:
import asyncio
from nextorm import AsyncDatabase, Entity, PK, Req, db_session
class Task(Entity):
id: PK[int]
title: Req[str]
done: Req[bool]
async def main() -> None:
db = AsyncDatabase(entities=[Task])
await db.bind("sqlite", ":memory:")
await db.generate_mapping(create_tables=True)
async with db_session:
Task(title="Buy milk", done=False)
results = await db.aselect(Task).filter(Task.done == False).fetch_all()
# or using the class-level shortcut:
results = await Task.aselect().filter(Task.done == False).fetch_all()
task = await Task.aget(title="Buy milk") # None if not found
print(results)
asyncio.run(main())
Entity registration¶
Entities register themselves globally as soon as their class is defined, so you
can pass entities=[...] to the Database constructor
or call register() later — whichever is more
convenient.
If you have only one database instance you can omit entities entirely and
let generate_mapping() discover all entities
that have been imported:
import myapp.models # imports ensure entity classes are defined
db = Database()
db.bind("sqlite", ":memory:")
db.generate_mapping(create_tables=True)
Next steps¶
Defining Entities — field types, defaults, constraints, inheritance
The Query API — filtering, ordering, pagination, aggregates
Sessions & Transactions — transactions, commit, rollback, flush
Relations — one-to-many, many-to-many, eager loading
Async Usage — async API and mixing sync/async databases
Migrations — schema migrations and CLI