SQLAlchemy Compatibility Mode¶
Saffier already supports SQLAlchemy-style expressions via Model.columns.<name>.
For progressive migrations from legacy SQLAlchemy models, you can opt in to
class-attribute compatibility so Model.<name> resolves to SQLAlchemy columns.
Enable Per Model¶
import saffier
import sqlalchemy
class Workspace(saffier.SQLAlchemyModelMixin, saffier.StrictModel):
id = saffier.IntegerField(primary_key=True, autoincrement=True)
name = saffier.CharField(max_length=255)
class Meta:
registry = models
statement = sqlalchemy.select(Workspace.id).where(Workspace.id == 1)
Enable Once On An Abstract Base¶
If many models need this mode, declare it once on an abstract base model:
class SACompatBase(saffier.SQLAlchemyModelMixin, saffier.StrictModel):
class Meta:
abstract = True
class Workspace(SACompatBase):
id = saffier.IntegerField(primary_key=True, autoincrement=True)
name = saffier.CharField(max_length=255)
class Meta:
registry = models
Concrete subclasses inherit the compatibility behavior automatically.
What Works¶
On opted-in concrete models:
sqlalchemy.select(Workspace.id)
sqlalchemy.select(Workspace.id).where(Workspace.id == some_value)
sqlalchemy.select(Workspace.id).order_by(Workspace.id)
Foreign keys are exposed as scalar aliases using SQLAlchemy-style names:
# for `owner = saffier.ForeignKey(User, ...)`
Workspace.owner_id
What Does Not Work¶
Relationship collections and reverse relations are not scalar columns:
- Many-to-many fields such as
Workspace.tags - Reverse relationship fields
RefForeignKeyhelper fields
For these, continue using Saffier's relationship and queryset APIs.
Compatibility Notes¶
- This mode is explicit and opt-in only.
- Non-opted-in models keep existing behavior, so
Model.idstill raisesAttributeError. - Existing Saffier query patterns keep working, including
Model.columns.<name>, keyword filters, andQ.
FAQ¶
Can I enable this once in an abstract base model?¶
Yes. All concrete subclasses inherit the compatibility mode. You do not need to
repeat SQLAlchemyModelMixin on every child model.
Does this change normal Saffier query behavior?¶
No. It only adds SQLAlchemy Core style class-attribute access for opted-in concrete models.