mirror of
https://github.com/sqlalchemy/sqlalchemy.git
synced 2026-05-26 10:32:33 -04:00
5329fc481e
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
156 lines
4.0 KiB
Python
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()
|