Introduction to the ORM
The ORM implements Active Record: a class describes a table and an instance represents a row. It combines attributes, casts, queries, relationships and events. Database manages connections, drivers, SQL and transactions; the ORM builds plans on that same infrastructure.
Architecture and lifecycle
Section titled “Architecture and lifecycle”flowchart TD
C["Controller / service / command"] --> M["Model: attributes and lifecycle"]
M --> Q["ModelQueryBuilder: query plan"]
Q --> R["ConnectionResolver"]
R --> D["Database connection manager"]
D --> S["SQL compiler and driver"]
S --> B[(Database)]
B --> H["Rows → casts → model hydration"]
H --> CWhen a class is declared, ModelMeta collects columns, resolves the table and primary key, and prepares casts, accessors, scopes and listeners. Declaring a model never creates or alters tables: use migrations.
Article({...})builds a new in-memory instance and applies mass assignment rules.await article.save()generates an INSERT, maintains declared timestamps, adopts the generated identity and synchronizes original state.await Article.find(id)retrieves a row, applies casts and creates a persisted instance. It returnsNonewhen absent.- Attribute changes are tracked against the original snapshot. Another
save()writes those differences through UPDATE. delete()removes the row or stamps its soft delete column.
Declarations and builders are synchronous; terminals accessing data are asynchronous. Use these examples from a controller, service, command or task after application boot. The Database provider installs ConnectionResolver; querying before that setup raises OrmConfigurationException.
Choosing an API
Section titled “Choosing an API”| Need | API |
|---|---|
| Row with attribute policy, state and events | A Model instance |
| Entity and relationship queries | Article.query() or a delegated entry such as Article.where(...) |
| Table rows, aggregates and writes without an entity lifecycle | DB.table(...) |
| Connections, SQL and transactions | Database and DB |
DB.table() does not run model casts, accessors, events or scopes. A model builder hydrates entities, but its mass writes also skip each instance’s lifecycle. Choose deliberately when a rule depends on events.
Learning path
Section titled “Learning path”- Models and attributes: generator, columns, configuration and serialization.
- Persistence and state: the complete class and instance API.
- Queries: fluent language, aggregates and mass operations.
- Relationships, operations and N+1.
- Scopes, events and soft deletes.
- Collections and pagination.
- Factories and testing and schema types.
The ORM uses database configuration; it has no separate connection file. A model operation does not automatically make several actions transactional: define the unit with transactions. Python state is not automatically reverted by an SQL rollback; retrieve a fresh instance after rolling back.
A scope constrains a query, an event wraps an instance operation, and soft deletion changes deletion writes and visibility. These mechanisms do not replace authorization or SQL constraints. Verify their interactions with ORM tests.