简体   繁体   English

多对多关联表上的SQLAlchemy关系

[英]SQLAlchemy relationship on many-to-many association table

I am trying to build a relationship to another many-to-many relationship, the code looks like this: 我正在尝试与另一个多对多关系建立关系,代码如下所示:

from sqlalchemy import Column, Integer, ForeignKey, Table, ForeignKeyConstraint, create_engine
from sqlalchemy.orm import relationship, backref, scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

supervision_association_table = Table('supervision', Base.metadata,
    Column('supervisor_id', Integer, ForeignKey('supervisor.id'), primary_key=True),
    Column('client_id', Integer, ForeignKey('client.id'), primary_key=True)
)

class User(Base):
    __tablename__ = 'user'

    id = Column(Integer, primary_key=True)

class Supervisor(User):
    __tablename__ = 'supervisor'
    __mapper_args__ = {'polymorphic_identity': 'supervisor'}

    id = Column(Integer, ForeignKey('user.id'), primary_key = True)

    schedules = relationship("Schedule", backref='supervisor')

class Client(User):
    __tablename__ = 'client'
    __mapper_args__ = {'polymorphic_identity': 'client'}

    id = Column(Integer, ForeignKey('user.id'), primary_key = True)

    supervisor = relationship("Supervisor", secondary=supervision_association_table,
                                backref='clients')
    schedules = relationship("Schedule", backref="client")

class Schedule(Base):
    __tablename__ = 'schedule'
    __table_args__ = (
        ForeignKeyConstraint(['client_id', 'supervisor_id'], ['supervision.client_id', 'supervision.supervisor_id']),
    )

    id = Column(Integer, primary_key=True)
    client_id = Column(Integer, nullable=False)
    supervisor_id = Column(Integer, nullable=False)

engine = create_engine('sqlite:///temp.db')
db_session = scoped_session(sessionmaker(bind=engine))
Base.metadata.create_all(bind=engine)

What I want to do is to relate a schedule to a specific Client-Supervisor-relationship, though I have not found out how to do it. 我想要做的是将时间表与特定的客户 - 主管关系联系起来,尽管我还没有找到如何做到这一点。 Going through the SQLAlchemy documentation I found a few hints, resulting in the ForeignKeyConstraint on the Schedule-Table. 通过SQLAlchemy文档,我发现了一些提示,导致Schedule-Table上的ForeignKeyConstraint。

How can I specify the relationship to have this association work? 如何指定关联以使此关联有效?

You need to map supervision_association_table so that you can create relationships to/from it. 您需要映射supervision_association_table,以便您可以创建与之关系。

I may be glossing over something here, but it seems like since you have many-to-many here you really can't have Client.schedules - if I say Client.schedules.append(some_schedule), which row in "supervision" is it pointing to ? 我可能会在这里讨论一些事情,但似乎因为你在这里有多对多你真的不能有Client.schedules - 如果我说Client.schedules.append(some_schedule),那么“监督”中的哪一行是它指向? So the example below provides a read-only "rollup" accessor for those which joins the Schedule collections of each SupervisorAssociation. 因此,下面的示例为那些加入每个SupervisorAssociation的Schedule集合的访问者提供了只读“汇总”访问器。 The association_proxy extension is used to conceal, when convenient, the details of the SupervisionAssociation object. association_proxy扩展用于在方便时隐藏SupervisionAssociation对象的详细信息。

from sqlalchemy import Column, Integer, ForeignKey, Table, ForeignKeyConstraint, create_engine
from sqlalchemy.orm import relationship, backref, scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.associationproxy import association_proxy
from itertools import chain

Base = declarative_base()

class SupervisionAssociation(Base):
    __tablename__ = 'supervision'

    supervisor_id = Column(Integer, ForeignKey('supervisor.id'), primary_key=True)
    client_id = Column(Integer, ForeignKey('client.id'), primary_key=True)

    supervisor = relationship("Supervisor", backref="client_associations")
    client = relationship("Client", backref="supervisor_associations")
    schedules = relationship("Schedule")

class User(Base):
    __tablename__ = 'user'

    id = Column(Integer, primary_key=True)

class Supervisor(User):
    __tablename__ = 'supervisor'
    __mapper_args__ = {'polymorphic_identity': 'supervisor'}

    id = Column(Integer, ForeignKey('user.id'), primary_key = True)

    clients = association_proxy("client_associations", "client", 
                        creator=lambda c: SupervisionAssociation(client=c))

    @property
    def schedules(self):
        return list(chain(*[c.schedules for c in self.client_associations]))

class Client(User):
    __tablename__ = 'client'
    __mapper_args__ = {'polymorphic_identity': 'client'}

    id = Column(Integer, ForeignKey('user.id'), primary_key = True)

    supervisors = association_proxy("supervisor_associations", "supervisor", 
                        creator=lambda s: SupervisionAssociation(supervisor=s))
    @property
    def schedules(self):
        return list(chain(*[s.schedules for s in self.supervisor_associations]))

class Schedule(Base):
    __tablename__ = 'schedule'
    __table_args__ = (
        ForeignKeyConstraint(['client_id', 'supervisor_id'], 
        ['supervision.client_id', 'supervision.supervisor_id']),
    )

    id = Column(Integer, primary_key=True)
    client_id = Column(Integer, nullable=False)
    supervisor_id = Column(Integer, nullable=False)
    client = association_proxy("supervisor_association", "client")

engine = create_engine('sqlite:///temp.db', echo=True)
db_session = scoped_session(sessionmaker(bind=engine))
Base.metadata.create_all(bind=engine)

c1, c2 = Client(), Client()
sp1, sp2 = Supervisor(), Supervisor()
sch1, sch2, sch3 = Schedule(), Schedule(), Schedule()

sp1.clients = [c1]
c2.supervisors = [sp2]
c2.supervisor_associations[0].schedules = [sch1, sch2]
c1.supervisor_associations[0].schedules = [sch3]

db_session.add_all([c1, c2, sp1, sp2, ])
db_session.commit()


print c1.schedules
print sp2.schedules

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 SQLAlchemy使用关联表以多对多关系插入数据 - SQLAlchemy Inserting Data in a Many-to-Many Relationship with Association Table SQLAlchemy单表上的多对多关系 - SQLAlchemy Many-to-Many Relationship on a Single Table 自引用多对多关系与 SQLAlchemy 中的关联 object - Self-referencing many-to-many relationship with an association object in SQLAlchemy SQLAlchemy使用Association配置与self的多对多关系 - SQLAlchemy configuring many-to-many relationship to self using Association 插入 flask SQLAlchemy 与关联表以多对多关系插入数据时出错 - Error while inseting flask SQLAlchemy Inserting Data in a Many-to-Many Relationship with Association Table SQLAlchemy 1.4 与关联表的多对多关系重叠关系的警告 - SQLAlchemy 1.4 warnings on overlapping relationships with a many-to-many relationship with association table 在SQLAlchemy多对多关联表中存储对其他行的引用 - Storing reference to other rows in SQLAlchemy Many-to-Many association table Sqlalchemy:template_id和部门之间多对多关系的关联表。 如何删除关系? - Sqlalchemy : association table for many-to-many relationship between template_id and department. How can I delete a relationship? 与关联对象在同一个表上的多对多关系 - Many-to-many relationship on same table with association object 单个表错误上的SQLAlchemy多对多关系:NoReferencedTableError - SQLAlchemy Many-to-Many Relationship on a Single Table Error: NoReferencedTableError
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM