To create separated SQLAlchemy model for domain and persistance you should use mapper
, instead of declarative mapping style. Example:
# entities.py
class Table:
def __init__(self, table_id: int):
self.id = table_id
class Restaurant:
def __init__(self, restaurant_id: int, tables: List[Table]):
self.id = restaurant_id
self.tables = tables
# orm.py
from sqlalchemy import Boolean, Column, ForeignKey, Integer, MetaData, create_engine
from sqlalchemy import Table as sa_Table
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import mapper, relationship
from entities import Restaurant, Table
SQLALCHEMY_DATABASE_URI = "sqlite:///" # your db uri
engine = create_engine(SQLALCHEMY_DATABASE_URI)
metadata = MetaData(bind=engine)
Base = declarative_base(metadata=metadata)
restaurant = sa_Table(
"restaurant",
metadata,
Column("id", Integer, primary_key=True, autoincrement=True),
)
table = sa_Table(
"table",
metadata,
Column("id", Integer, primary_key=True, autoincrement=True),
Column("restaurant_id", Integer, ForeignKey("restaurant.id"))
)
def run_mappers():
"""
Provides mapping between db tables and domain models.
"""
mapper(
Restaurant,
restaurant,
properties={"tables": relationship(Table, backref="restaurant")},
)
mapper(Table, table)
run_mappers() # it should be executed in the app runtime
If you need more context, here is my repo implementing full python project in DDD style (using Port and adapters architecture): https://github.com/jorzel/opentable
I have recently written a blog post about it: https://jorzel.hashnode.dev/persistence-and-domain-model-separation-using-sqlalchemy-orm.
There is also a great book (in python) covering this topic: https://github.com/cosmicpython/book