Models API¶
Model¶
Model ¶
Bases: BaseModel
Base model class for RestMachine ORM.
Provides ActiveRecord-style CRUD operations and integrates with Pydantic for validation. Models are compatible with RestMachine for automatic API integration.
Example
class User(Model): ... model_backend: ClassVar[Backend] = InMemoryBackend() ... ... id: str = Field(primary_key=True) ... email: str = Field(unique=True) ... name: str ... user = User.create(id="123", email="alice@example.com", name="Alice") user.name = "Alice Smith" user.save()
Alternative syntax using class parameter:
class User(Model, model_backend=InMemoryBackend()): ... id: str = Field(primary_key=True) ... name: str
Functions¶
__init_subclass__ ¶
Collect hooks from mixins when model class is defined.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
model_backend
|
Optional[Backend]
|
Optional backend to use for this model (alternative to ClassVar) |
None
|
**kwargs
|
Any
|
Additional arguments passed to parent |
{}
|
Source code in packages/restmachine-orm/src/restmachine_orm/models/base.py
create
classmethod
¶
Create and save a new record in one operation.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
**kwargs
|
Any
|
Field values for the new record |
{}
|
Returns:
Type | Description |
---|---|
Model
|
Created and saved model instance |
Raises:
Type | Description |
---|---|
ValidationError
|
If field validation fails |
DuplicateKeyError
|
If unique constraint is violated |
Example
user = User.create(id="123", email="alice@example.com", name="Alice")
Source code in packages/restmachine-orm/src/restmachine_orm/models/base.py
upsert
classmethod
¶
Create or update a record (upsert).
If a record with the same key exists, it will be overwritten. Unlike create(), this does not raise DuplicateKeyError.
Callbacks
- Calls all @before_save methods before persisting
- Calls all @after_save methods after persisting
Parameters:
Name | Type | Description | Default |
---|---|---|---|
**kwargs
|
Any
|
Field values for the record |
{}
|
Returns:
Type | Description |
---|---|
Model
|
Upserted and saved model instance |
Raises:
Type | Description |
---|---|
ValidationError
|
If field validation fails |
Example
user = User.upsert(id="123", email="alice@example.com", name="Alice")
If user with id=123 exists, it will be overwritten¶
Source code in packages/restmachine-orm/src/restmachine_orm/models/base.py
save ¶
Validate and save this record to the database.
Creates a new record if not persisted, otherwise updates existing.
Callbacks
- Calls all @before_save methods before persisting
- Calls all @after_save methods after persisting
Returns:
Type | Description |
---|---|
Model
|
Self for method chaining |
Raises:
Type | Description |
---|---|
ValidationError
|
If field validation fails |
Example
user = User(id="123", name="Alice") user.save() # Validates and saves
user.name = "Alice Smith" user.save() # Validates and updates
Source code in packages/restmachine-orm/src/restmachine_orm/models/base.py
delete ¶
Delete this record from the database.
Returns:
Type | Description |
---|---|
bool
|
True if deleted successfully |
Example
user.delete()
Source code in packages/restmachine-orm/src/restmachine_orm/models/base.py
get
classmethod
¶
Get a single record by primary key or filters.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
**filters
|
Any
|
Filter conditions (typically primary key) |
{}
|
Returns:
Type | Description |
---|---|
Optional[Model]
|
Model instance, or None if not found |
Example
user = User.get(id="123") if user: ... print(user.name)
Source code in packages/restmachine-orm/src/restmachine_orm/models/base.py
find_by
classmethod
¶
Find the first record matching conditions (eager execution).
This method executes immediately and returns the first matching record. For lazy query building, use where() instead.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
**conditions
|
Any
|
Filter conditions (all ANDed together) |
{}
|
Returns:
Type | Description |
---|---|
Optional[Model]
|
First matching model instance, or None if not found |
Examples:
>>> # Find first user with email
>>> user = User.find_by(email="alice@example.com")
>>> if user:
... print(user.name)
Source code in packages/restmachine-orm/src/restmachine_orm/models/base.py
where
classmethod
¶
Create a lazy query builder for finding records.
Returns a QueryBuilder that doesn't execute until results are accessed (via .all(), .first(), .last(), iteration, etc.)
Supports both field expressions and keyword arguments.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
*expressions
|
Any
|
Field expressions like User.age > 25 |
()
|
**conditions
|
Any
|
Keyword filter conditions (all ANDed together) |
{}
|
Returns:
Type | Description |
---|---|
QueryBuilder
|
QueryBuilder instance for chaining |
Examples:
>>> # Field expressions (new style)
>>> users = User.where(User.age > 25).all()
>>> users = User.where((User.age >= 18) & (User.age <= 65)).all()
>>> users = User.where((User.role == "admin") | (User.role == "moderator")).all()
Source code in packages/restmachine-orm/src/restmachine_orm/models/base.py
Field¶
Field ¶
Field(default: Any = PydanticUndefined, *, default_factory: Optional[Callable[[], Any]] = None, alias: Optional[str] = None, title: Optional[str] = None, description: Optional[str] = None, examples: Optional[list[Any]] = None, gt: Optional[float] = None, ge: Optional[float] = None, lt: Optional[float] = None, le: Optional[float] = None, min_length: Optional[int] = None, max_length: Optional[int] = None, pattern: Optional[str] = None, primary_key: bool = False, unique: bool = False, index: bool = False, searchable: bool = False, auto_now: bool = False, auto_now_add: bool = False, db_column: Optional[str] = None, gsi_partition_key: Optional[str] = None, gsi_sort_key: Optional[str] = None, analyzer: Optional[str] = None, **extra: Any) -> FieldInfo
Define a model field with validation and ORM metadata.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
default
|
Any
|
Default value for the field |
PydanticUndefined
|
default_factory
|
Optional[Callable[[], Any]]
|
Factory function for default values |
None
|
alias
|
Optional[str]
|
Alternative name for the field |
None
|
title
|
Optional[str]
|
Human-readable title |
None
|
description
|
Optional[str]
|
Field description |
None
|
examples
|
Optional[list[Any]]
|
Example values |
None
|
gt
|
Optional[float]
|
Greater than validation |
None
|
ge
|
Optional[float]
|
Greater than or equal validation |
None
|
lt
|
Optional[float]
|
Less than validation |
None
|
le
|
Optional[float]
|
Less than or equal validation |
None
|
min_length
|
Optional[int]
|
Minimum string/list length |
None
|
max_length
|
Optional[int]
|
Maximum string/list length |
None
|
pattern
|
Optional[str]
|
Regex pattern for string validation |
None
|
primary_key
|
bool
|
Whether this is the primary key |
False
|
unique
|
bool
|
Whether values must be unique |
False
|
index
|
bool
|
Whether to create a database index |
False
|
searchable
|
bool
|
Whether to enable full-text search (OpenSearch) |
False
|
auto_now
|
bool
|
Auto-update timestamp on save |
False
|
auto_now_add
|
bool
|
Auto-set timestamp on create |
False
|
db_column
|
Optional[str]
|
Custom database column name |
None
|
gsi_partition_key
|
Optional[str]
|
DynamoDB GSI partition key name |
None
|
gsi_sort_key
|
Optional[str]
|
DynamoDB GSI sort key name |
None
|
analyzer
|
Optional[str]
|
OpenSearch text analyzer |
None
|
**extra
|
Any
|
Additional Pydantic field arguments |
{}
|
Returns:
Type | Description |
---|---|
FieldInfo
|
FieldInfo object with ORM metadata |
Example
class User(Model): ... id: str = Field(primary_key=True) ... email: str = Field(unique=True, index=True) ... name: str = Field(max_length=100, searchable=True) ... age: int = Field(ge=0, le=150) ... created_at: datetime = Field(auto_now_add=True)
Decorators¶
partition_key¶
partition_key ¶
Decorator to mark a method as the partition key (hash key) generator.
Used for DynamoDB tables to define composite partition keys. The decorated method should return a string that will be used as the partition key value.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
func
|
Callable[[Model], str]
|
Method that generates the partition key string |
required |
Returns:
Type | Description |
---|---|
Callable[[Model], str]
|
Decorated method with metadata |
Example
class TodoItem(Model): ... user_id: str ... todo_id: str ... ... @partition_key ... def pk(self) -> str: ... return f"USER#{self.user_id}"
Note
Only one method per model should be decorated with @partition_key. The method name is conventionally 'pk' but can be anything.
Source code in packages/restmachine-orm/src/restmachine_orm/models/decorators.py
sort_key¶
sort_key ¶
Decorator to mark a method as the sort key (range key) generator.
Used for DynamoDB tables to define composite sort keys. The decorated method should return a string that will be used as the sort key value.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
func
|
Callable[[Model], str]
|
Method that generates the sort key string |
required |
Returns:
Type | Description |
---|---|
Callable[[Model], str]
|
Decorated method with metadata |
Example
class TodoItem(Model): ... user_id: str ... created_at: datetime ... todo_id: str ... ... @partition_key ... def pk(self) -> str: ... return f"USER#{self.user_id}" ... ... @sort_key ... def sk(self) -> str: ... return f"TODO#{self.created_at.isoformat()}#{self.todo_id}"
Note
Only one method per model should be decorated with @sort_key. The method name is conventionally 'sk' but can be anything.
Source code in packages/restmachine-orm/src/restmachine_orm/models/decorators.py
DynamoDB-Specific Decorators¶
The following decorators are available for DynamoDB backend (in restmachine_orm.models.decorators
):
gsi_partition_key(index_name)
- Mark method as GSI partition key generatorgsi_sort_key(index_name)
- Mark method as GSI sort key generator
These are used with the DynamoDB backend to define Global Secondary Index keys. See the DynamoDB Backend documentation for usage examples.