ORM and queries
Orionis combines Active Record models, fluent queries, relationships, and factories. Models describe attributes and behavior; Database owns connections, SQL compilation, and transactions. The engine is not part of the model API.
Declarations and builders are synchronous. Reading or writing data requires await. Bootstrap the application and create tables through migrations before querying; declaring a class does not create its table.
From a model to a persisted record
Section titled “From a model to a persisted record”A model belongs in your application’s code, normally app/models. Its declared columns must match an existing table:
- Define the model and its
fillablepolicy following models and attributes. - Create a matching migration, then run
uv run python -B reactor migratefrom the application root. Column declarations on the model alone do not execute this step. - Use the model from an async controller, command, job, or service after application bootstrap. Construct an instance with trusted or validated data, then check the boolean returned by
await instance.save(). - Retrieve data with
await ModelClass.where(...).get()orawait ModelClass.find(id).find()can returnNone; handle that case before accessing attributes.
When you only need rows and aggregates, raw table queries through DB.table() avoid defining a model. Use model queries when you need casts, events, relationships, or soft deletes.
- Models, attributes, and persistence: define an entity, protect input, and save changes.
- Query, update, and paginate: models versus tables, filters, joins, aggregates, and bulk writes.
- Relate and load models: direct relationships, eager loading, and pivot tables.
- Events, scopes, and soft deletes: domain behavior, query policies, and logical deletion.
- Factories and testing: reproducible data, states, sequences, and controlled persistence.
- Schema types and constraints: type catalog, modifiers, composite keys, and shared definitions.
Examples that only declare models or compose plans perform no database access. Async facade examples require bootstrap and matching tables; each chapter explains its prerequisites. Python 3.14 or later is required.
The database provider installs a manager in ConnectionResolver; querying without that bridge raises OrmConfigurationException. The ORM consumes database configuration without a separate configuration file. QueryBuilderProvider registers the DB singleton gateway; each query call creates its own builder.