Inheritance Hierarchies: Loading a model created with parent class in same session

20 views
Skip to first unread message

David Bücher

unread,
Jun 19, 2022, 3:52:48 PM6/19/22
to sqlalchemy
To avoid writing a function selecting the correct class for a 'type' value, I would like to create models using the parent class ('Employee') and 'type' instead of using the child class ('Manager', 'Engineer') in the first place. I noticed that the resulting object is not of the respecting child class (e.g. 'Manager'), even after re-querying it with the child class or with with_polymorphic. However, only in a new session this works out. Is there a way to achieve this without opening a new session?

Here is my example script - I am using sqlalchemy version 1.4.37:

from sqlalchemy import Column, Integer, String, create_engine
from sqlalchemy.orm import declarative_base, \
    relationship, sessionmaker

engine = create_engine('sqlite:///:memory:', echo=True)
Base = declarative_base()

class Employee(Base):
    __tablename__ = "employee"
    id = Column(Integer, primary_key=True)
    name = Column(String(50))
    type = Column(String(50))

    __mapper_args__ = {
        "polymorphic_identity": "employee",
        "polymorphic_on": type,
        'with_polymorphic': '*'
    }

class Manager(Employee):
    manager_data = Column(String(50))

    __mapper_args__ = {
        "polymorphic_identity": "manager"
    }

Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
manager = Employee(name='name of Manager', type='manager')
session.add(manager)
session.flush()
manager_id = manager.id
session.commit()

# doesn't work:
m0 = session.query(Employee).filter_by(id=manager_id).first()
print(">>", m0.__mapper_args__['polymorphic_identity'])
try:
    print(m0.manager_data)
except:
    print(">> didn't work")

# doesn't work:
m = session.query(Manager).filter_by(id=manager_id).first()
print(">>", m.__mapper_args__['polymorphic_identity'])
try:
    print(m.manager_data)
except:
    print(">> didn't work")

# works:
session.close()
session2 = Session()
m1 = session2.query(Employee).filter_by(id=manager_id).first()
print(">>", m1.__mapper_args__['polymorphic_identity'])
print(m1.manager_data)

# works:
m = session2.query(Manager).filter_by(id=manager_id).first()
print(">>", m.__mapper_args__['polymorphic_identity'])
print(m.manager_data)

session2.close()

Thanks,
David

Mike Bayer

unread,
Jun 20, 2022, 11:12:00 AM6/20/22
to noreply-spamdigest via sqlalchemy


On Sun, Jun 19, 2022, at 3:52 PM, David Bücher wrote:
To avoid writing a function selecting the correct class for a 'type' value, I would like to create models using the parent class ('Employee') and 'type' instead of using the child class ('Manager', 'Engineer') in the first place.

that pattern is not supported by SQLAlchemy's inheritance feature.



I noticed that the resulting object is not of the respecting child class (e.g. 'Manager'), even after re-querying it with the child class or with with_polymorphic. However, only in a new session this works out.

that's because the object you've created is already in the identity map (https://docs.sqlalchemy.org/en/14/glossary.html#term-identity-map) and is not re-constructed.



Is there a way to achieve this without opening a new session?

overall just simply dont use the inheritance feature and just have an Employee class with a type column.   it does not appear you seeking to make any use of the inheritance feature.



--
SQLAlchemy -
The Python SQL Toolkit and Object Relational Mapper
 
 
To post example code, please provide an MCVE: Minimal, Complete, and Verifiable Example. See http://stackoverflow.com/help/mcve for a full description.
---
You received this message because you are subscribed to the Google Groups "sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+...@googlegroups.com.

Reply all
Reply to author
Forward
0 new messages