Skip to content

Instantly share code, notes, and snippets.

@nicoddemus
Last active December 7, 2021 21:45
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nicoddemus/26de7bbcdfa9ed4b14fcfdde72b1d63f to your computer and use it in GitHub Desktop.
Save nicoddemus/26de7bbcdfa9ed4b14fcfdde72b1d63f to your computer and use it in GitHub Desktop.
Replicate the example from https://docs.sqlalchemy.org/en/14/_modules/examples/inheritance/joined.html using classic mappings
from pathlib import Path
import attr
from sqlalchemy import Column
from sqlalchemy import create_engine
from sqlalchemy import ForeignKey
from sqlalchemy import Integer
from sqlalchemy import MetaData
from sqlalchemy import String
from sqlalchemy import Table
from sqlalchemy.orm import registry
from sqlalchemy.orm import relationship
from sqlalchemy.orm import sessionmaker
class Person:
pass
@attr.s(auto_attribs=True)
class Manager(Person):
name: str
data: str
@attr.s(auto_attribs=True)
class Engineer(Person):
name: str
info: int
@attr.s(auto_attribs=True)
class Company:
people: list[Person]
metadata = MetaData()
mapper_registry = registry()
persons_table = Table(
"person",
metadata,
Column("id", Integer, primary_key=True, autoincrement=True),
Column("type", String(50)),
)
managers_table = Table(
"manager",
metadata,
Column('id', ForeignKey("person.id"), primary_key=True),
Column("name", String(50)),
Column("data", String(50)),
)
engineers_table = Table(
"engineer",
metadata,
Column('id', ForeignKey("person.id"), primary_key=True),
Column("name", String(50)),
Column("info", Integer),
)
company_table = Table(
"company",
metadata,
Column("id", Integer, primary_key=True),
)
company_2_people_table = Table(
"company_2_people",
metadata,
Column("id", Integer, primary_key=True, autoincrement=True),
Column("company_id", ForeignKey("company.id")),
Column("person_id", ForeignKey("person.id")),
)
person_mapper = mapper_registry.map_imperatively(
Person,
persons_table,
polymorphic_identity="person",
polymorphic_on=persons_table.c.type,
)
manager_mapper = mapper_registry.map_imperatively(
Manager,
managers_table,
inherits=person_mapper,
polymorphic_identity="manager",
)
engineer_mapper = mapper_registry.map_imperatively(
Engineer,
engineers_table,
inherits=person_mapper,
polymorphic_identity="engineer",
)
company_mapper = mapper_registry.map_imperatively(
Company,
company_table,
properties={
"people": relationship(
person_mapper,
secondary=company_2_people_table,
collection_class=list,
),
},
)
fn = Path(__file__).with_suffix(".db")
fn.unlink(missing_ok=True)
engine = create_engine(f"sqlite:///{fn}", echo=False)
metadata.create_all(engine)
Session = sessionmaker(bind=engine)
with Session() as session:
m1 = Manager(name="Manager 1", data="Manager Data")
m2 = Manager(name="Manager 2", data="Manager Data")
e1 = Engineer(name="Eng 1", info=10)
e2 = Engineer(name="Eng 2", info=30)
company = Company([e2, m1, e1, m2])
session.add(company)
session.commit()
with Session() as session:
print(session.query(Company).get(1))
@nicoddemus
Copy link
Author

nicoddemus commented Apr 2, 2021

Asked for help on Stack Overflow: https://stackoverflow.com/questions/66921914/using-polymorphic-classes-in-classic-mappings-style

Found the solution, the code above now works as expected. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment