Files
sqlalchemy/examples/inheritance/joined.py
T
Mike Bayer 0a40d5c4a0 modernize and repair inheritance examples
remarkably, the examples for concrete and single were still
using classical mappings.    Ensure all three examples use
modern declarative patterns, each illustrate the identical set
of query operations.  Use back_populates, flat=True for joins,
etc. ensure flake8 linting, correct links and add a link back
from newly reworked inheritance documentation.

Change-Id: I8465a9badbb0eda804f457ccac599f051ee3c27c
(cherry picked from commit 5329fc481e)
2017-05-16 09:53:02 -04:00

156 lines
4.0 KiB
Python

"""Joined-table (table-per-subclass) inheritance example."""
from sqlalchemy import Column, Integer, String, \
ForeignKey, create_engine, inspect, or_
from sqlalchemy.orm import relationship, Session, with_polymorphic
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Company(Base):
__tablename__ = 'company'
id = Column(Integer, primary_key=True)
name = Column(String(50))
employees = relationship(
"Person",
back_populates='company',
cascade='all, delete-orphan')
def __repr__(self):
return "Company %s" % self.name
class Person(Base):
__tablename__ = 'person'
id = Column(Integer, primary_key=True)
company_id = Column(ForeignKey('company.id'))
name = Column(String(50))
type = Column(String(50))
company = relationship("Company", back_populates="employees")
__mapper_args__ = {
'polymorphic_identity': 'person',
'polymorphic_on': type
}
def __repr__(self):
return "Ordinary person %s" % self.name
class Engineer(Person):
__tablename__ = 'engineer'
id = Column(ForeignKey('person.id'), primary_key=True)
status = Column(String(30))
engineer_name = Column(String(30))
primary_language = Column(String(30))
__mapper_args__ = {
'polymorphic_identity': 'engineer',
}
def __repr__(self):
return (
"Engineer %s, status %s, engineer_name %s, "
"primary_language %s" %
(
self.name, self.status,
self.engineer_name, self.primary_language)
)
class Manager(Person):
__tablename__ = 'manager'
id = Column(ForeignKey('person.id'), primary_key=True)
status = Column(String(30))
manager_name = Column(String(30))
__mapper_args__ = {
'polymorphic_identity': 'manager',
}
def __repr__(self):
return "Manager %s, status %s, manager_name %s" % (
self.name, self.status, self.manager_name)
engine = create_engine('sqlite://', echo=True)
Base.metadata.create_all(engine)
session = Session(engine)
c = Company(name='company1', employees=[
Manager(
name='pointy haired boss',
status='AAB',
manager_name='manager1'),
Engineer(
name='dilbert',
status='BBA',
engineer_name='engineer1',
primary_language='java'),
Person(name='joesmith'),
Engineer(
name='wally',
status='CGG',
engineer_name='engineer2',
primary_language='python'),
Manager(
name='jsmith',
status='ABA',
manager_name='manager2')
])
session.add(c)
session.commit()
c = session.query(Company).get(1)
for e in c.employees:
print(e, inspect(e).key, e.company)
assert set([e.name for e in c.employees]) == set(
['pointy haired boss', 'dilbert', 'joesmith', 'wally', 'jsmith'])
print("\n")
dilbert = session.query(Person).filter_by(name='dilbert').one()
dilbert2 = session.query(Engineer).filter_by(name='dilbert').one()
assert dilbert is dilbert2
dilbert.engineer_name = 'hes dilbert!'
session.commit()
c = session.query(Company).get(1)
for e in c.employees:
print(e)
# query using with_polymorphic.
eng_manager = with_polymorphic(Person, [Engineer, Manager])
print(
session.query(eng_manager).
filter(
or_(
eng_manager.Engineer.engineer_name == 'engineer1',
eng_manager.Manager.manager_name == 'manager2'
)
).all()
)
# illustrate join from Company.
# flat=True means the tables inside the "polymorphic join" will be aliased.
# not strictly necessary in this example but helpful for the more general
# case of joins involving inheritance hierarchies as well as joined eager
# loading.
eng_manager = with_polymorphic(Person, [Engineer, Manager], flat=True)
print(
session.query(Company).
join(
Company.employees.of_type(eng_manager)
).filter(
or_(eng_manager.Engineer.engineer_name == 'engineer1',
eng_manager.Manager.manager_name == 'manager2')
).all())
session.commit()