我有一对一对多关系的树,如下所示:
组织 - >操作 - >地区 - >区域 - >站点
organization
是顶级祖先。 site
有一个area_id
,area
有一个region_id
,依此类推。
对于组织下的每个实体,我希望能够通过site.organization
,area.organization
等关系快速访问组织祖先。
每个实体的relationship
看起来是什么样的?
答案 0 :(得分:2)
解决方案是对那些与组织没有直接关系的类使用composite "secondary" join。例如site:
class Site(Base):
organization = relationship(
"Organization",
secondary="join(Operation, Region).join(Area)",
uselist=False,
innerjoin=True,
viewonly=True)
虽然region应该只使用表操作作为辅助操作:
class Region(Base):
organization = relationship(
"Organization",
secondary="operation",
uselist=False,
innerjoin=True,
viewonly=True)
以上是仅显示关系配置的简化版本。下面是一个具体的例子:
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base
engine = create_engine("sqlite://")
Base = declarative_base()
Base.metadata.bind = engine
Session = sessionmaker()
class Organization(Base):
__tablename__ = 'organization'
id = Column(Integer, primary_key=True)
class Operation(Base):
__tablename__ = 'operation'
id = Column(Integer, primary_key=True)
organization_id = Column(ForeignKey('organization.id'))
organization = relationship("Organization")
class Region(Base):
__tablename__ = 'region'
id = Column(Integer, primary_key=True)
operation_id = Column(ForeignKey('operation.id'))
organization = relationship(
"Organization",
secondary="operation",
uselist=False, innerjoin=True, viewonly=True)
operation = relationship("Operation")
class Area(Base):
__tablename__ = 'area'
id = Column(Integer, primary_key=True)
region_id = Column(ForeignKey('region.id'))
organization = relationship(
"Organization",
secondary="join(Operation, Region)",
uselist=False, innerjoin=True, viewonly=True)
region = relationship("Region")
class Site(Base):
__tablename__ = 'site'
id = Column(Integer, primary_key=True)
area_id = Column(ForeignKey('area.id'))
organization = relationship(
"Organization",
secondary="join(Operation, Region).join(Area)",
uselist=False, innerjoin=True, viewonly=True)
area = relationship("Area")
Base.metadata.create_all()
session = Session()
session.add(Site(area=Area(region=Region(operation=Operation(organization=Organization())))))
session.commit()
site = session.query(Site).options(joinedload(Site.organization)).first()
print(site)
print(site.organization)
print(site.area.organization)
print(site.area.region.organization)
print(site.area.region.operation.organization)