Skip to content

SQL ORM mixins and collections#

Module: restalchemy.storage.sql.orm

This module provides ORM-like behavior for DM models:

  • ObjectCollection — collection API exposed as Model.objects.
  • SQLStorableMixin — mixin that adds save(), update(), delete() and integration with SQL tables.
  • SQLStorableWithJSONFieldsMixin — specialization for models with JSON fields.

ObjectCollection#

ObjectCollection implements the collection interface for SQL-backed models.

Key methods:

  • get_all(filters=None, session=None, cache=False, limit=None, order_by=None, locked=False)
  • Returns a list of model instances.
  • Uses filters (DM filter structures) to build WHERE clauses.
  • Can use per-session query cache when cache=True.
  • get_one(filters=None, session=None, cache=False, locked=False)
  • Returns exactly one model instance.
  • Raises RecordNotFound if no rows, HasManyRecords if more than one.
  • get_one_or_none(filters=None, session=None, cache=False, locked=False)
  • Returns a single instance or None if not found.
  • query(where_conditions, where_values, session=None, cache=False, limit=None, order_by=None, locked=False)
  • Executes a custom WHERE clause.
  • count(session=None, filters=None)
  • Returns the number of rows matching filters.

ObjectCollection uses:

  • The SQL dialect via engine.dialect.
  • The model's restore_from_storage() method to convert rows into DM models.

Loading relationships#

A relationship the query did not prefetch arrives as an identifier, and the model it names is read separately. get_all() and query() gather the identifiers of the whole page and read them one query per relationship, rather than one query per row, and do the same for what those objects point at in turn.

  • Rows of the page naming the same object are handed the same instance.
  • An identifier the page does not find is left as it arrived, so a row pointing at a missing record fails exactly as it did before.
  • A relationship declared with prefetch=True is read by the query that reads the page (a LEFT JOIN) and does not take part in this.
  • SQLStorableMixin.RELATIONSHIP_BATCH_SIZE (1000 by default) caps how many identifiers a single query asks for.

SQLStorableMixin#

SQLStorableMixin is intended to be combined with DM models to make them storable in SQL.

Requirements#

  • The DM model must have a valid __tablename__ string.
  • There must be at least one ID property (id_property=True).

Core responsibilities#

  • get_table()
  • Returns a SQLTable instance for the model, cached in __operational_storage__.
  • insert(session=None)
  • Inserts the model into the table using current property values.
  • Wraps dialect-specific exceptions into storage exceptions (e.g. conflicts).
  • save(session=None)
  • If the instance is not yet saved, calls insert().
  • Otherwise calls update().
  • update(session=None, force=False)
  • Updates the row when the model is dirty or force=True.
  • Validates the model before updating.
  • Ensures exactly one row is updated (otherwise raises).
  • delete(session=None)
  • Deletes the row corresponding to the model's ID properties.
  • restore_from_storage(**kwargs) (class method)
  • Converts database row values (simple types) to DM property values.
  • Constructs a model instance marked as saved.

Object collection binding#

SQLStorableMixin defines _ObjectCollection = ObjectCollection. In combination with base storage classes this provides:

  • Model.objects — a collection that uses ObjectCollection to perform queries.

Type conversion helpers#

  • to_simple_type(value) (class method)
  • Converts model instances or raw ID values to a form suitable for filters.
  • from_simple_type(value) (class method)
  • Converts raw ID values or prefetch results into model instances.

These helpers allow storage and API layers to work with IDs and prefetch structures transparently.


SQLStorableWithJSONFieldsMixin#

SQLStorableWithJSONFieldsMixin extends SQLStorableMixin for databases that do not support JSON fields natively.

Usage pattern:

  • Inherit from SQLStorableWithJSONFieldsMixin instead of SQLStorableMixin.
  • Define __jsonfields__ as an iterable of field names that store JSON data.

Behavior:

  • restore_from_storage()
  • For fields listed in __jsonfields__:
    • If the stored value is a string, parses it as JSON.
  • _get_prepared_data(properties=None)
  • For fields in __jsonfields__, dumps Python data structures to compact JSON strings.

This allows you to keep JSON fields in your DM models while persisting them as text in databases that lack native JSON support.