在SQLAlchemy中寻找祖先的关系

时间:2017-11-14 13:46:44

标签: python orm sqlalchemy

我有一对一对多关系的树,如下所示:

  

组织 - >操作 - >地区 - >区域 - >站点

organization是顶级祖先。 site有一个area_idarea有一个region_id,依此类推。

对于组织下的每个实体,我希望能够通过site.organizationarea.organization等关系快速访问组织祖先。

每个实体的relationship看起来是什么样的?

1 个答案:

答案 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)
相关问题