On 11/16/2016 10:18 AM, Michael Williamson wrote:
When using AbstractConcreteBase to implement inheritance with a
separate table per type (and no common table), it seems like properties
that are present on all of the subtypes are lifted up onto the super
type. Is there a way to get the same behaviour when using joined table
inheritance? For instance, at the moment, the below fails since
Employee.name doesn't exist. Is there a way to get Employee.name to be
automatically generated from the subtypes?
Joined table inheritance assumes column names are unique for a given
inheritance hierarchy unless special steps are taken to resolve how the
duplicate names will be handled. This is because multiple tables are
queried to produce a single row. This is not analogous to concrete
inheritance where each row is the product of only one table at a time.
In this case, to have engineer.name as well as employee.name, you'd need
to use a different attribute name to distinguish them, but also there's
no automatic movement of columns from the subclass to the superclass.
That would occur if Manager / Engineer were *single* table inheritance,
but not for joined.
from __future__ import unicode_literals
from sqlalchemy import create_engine, Column, Integer, String,
ForeignKey from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import Session
Base = declarative_base()
class Employee(Base):
__tablename__ = "employee"
__mapper_args__ = {
"polymorphic_on": "discriminator",
}
id = Column(Integer, primary_key=True)
discriminator = Column(String)
class Manager(Employee):
__tablename__ = "manager"
__mapper_args__ = {
"polymorphic_identity": "manager",
}
id = Column(Integer, ForeignKey(Employee.id), primary_key=True)
name = Column(String)
class Engineer(Employee):
__tablename__ = "engineer"
__mapper_args__ = {
"polymorphic_identity": "employee",
}
id = Column(Integer, ForeignKey(Employee.id), primary_key=True)
name = Column(String)
engine = create_engine("sqlite:///:memory:", echo=True)
Base.metadata.create_all(engine)
session = Session(engine)
session.add(Engineer(name="Jim"))
session.add(Manager(name="Jules"))
session.commit()
print(session.query(Employee.name).all())
For comparison, when using AbstractConcreteBase, it's possible to
reference Employee.name:
from __future__ import unicode_literals
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base,
AbstractConcreteBase from sqlalchemy.orm import Session
Base = declarative_base()
class Employee(AbstractConcreteBase, Base):
pass
class Manager(Employee):
__tablename__ = "manager"
__mapper_args__ = {
"polymorphic_identity": "manager",
"concrete": True
}
id = Column(Integer, primary_key=True)
name = Column(String)
class Engineer(Employee):
__tablename__ = "engineer"
__mapper_args__ = {
"polymorphic_identity": "employee",
"concrete": True,
}
id = Column(Integer, primary_key=True)
name = Column(String)
engine = create_engine("sqlite:///:memory:", echo=True)
Base.metadata.create_all(engine)
session = Session(engine)
session.add(Engineer(name="Jim"))
session.add(Manager(name="Jules"))
session.commit()
print(session.query(Employee.name).all())
Thanks (both in advance for this question, and for putting up with my
other questions!)
Michael
--
SQLAlchemy -
The Python SQL Toolkit and Object Relational Mapper
http://www.sqlalchemy.org/
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 [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.