mirror of
https://github.com/sqlalchemy/sqlalchemy.git
synced 2026-05-26 02:22:13 -04:00
0a40d5c4a0
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)
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()
|