Sqlalchemy协会代理和no_autoflush

时间:2016-06-29 20:22:35

标签: python sqlalchemy

我试图弄清楚为什么在将数据插入关联代理时如果首先访问关联代理数据,我需要使用no_autoflush块。下面是一个例子(使用MySQL):

from sqlalchemy import create_engine, Integer, Column, String, ForeignKey, UniqueConstraint
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship, scoped_session

Base = declarative_base()
engine = create_engine('{}://{}:{}@{}/{}'.format(...))
session_factory = sessionmaker(bind=engine)
Session = scoped_session(session_factory)

class DomainModel(Base):
    __tablename__ = 'domains'
    id = Column(Integer, primary_key=True)
    name = Column(String(255), nullable=False, unique=True)
    domains_to_servers = relationship("DomainServerModel", back_populates="domain")
    servers = association_proxy('domains_to_servers', 'server',
                                creator=lambda s: DomainServerModel(server=s))


class ServerModel(Base):
    __tablename__ = 'servers'
    id = Column(Integer, primary_key=True)
    name = Column(String(128), nullable=False, unique=True, index=True)
    domains_to_servers = relationship("DomainServerModel", back_populates="server")
    domains = association_proxy('domains_to_servers', 'domain',
                                creator=lambda d: DomainServerModel(domain=d))


class DomainServerModel(Base):
    __tablename__ = 'domains_to_servers'
    id = Column(Integer, primary_key=True)
    domain_id = Column(Integer, ForeignKey('domains.id'), nullable=False)
    server_id = Column(Integer, ForeignKey('servers.id'), nullable=False)
    server = relationship('ServerModel', back_populates="domains_to_servers")
    domain = relationship('DomainModel', back_populates="domains_to_servers")


def test():
     session = Session()
     with session.no_autoflush:
        s = session.query(ServerModel).filter_by(name='test.com').one()
        print(s.domains)
        d = DomainModel(name='test1.com')
        session.add(d)
        session.commit()
        s.domains.append(d)
        session.commit()

if __name__ == '__main__':
    Base.metadata.drop_all(engine)
    Base.metadata.create_all(engine)
    session = Session()
    session.add(ServerModel(name='test.com'))
    session.commit()
    test()

我尝试通过服务器/域关联代理添加新的domain_to_server映射。如果我不首先访问关联代理,即删除test()中的print语句,那么我可以添加域而不需要session.no_autoflush块。但是如果有print语句,那么如果没有带有IntegrityError的session.no_autoflush块,它将失败,并且在域到服务器表中,server_id不能为空。

我试图找出为什么这里需要no_autoflush块。我没有在association_proxy docs中看到任何提及它的内容。这是否就是这样,所有插入到association_proxy中的插入应该在no_autoflush bock中发生,以防它在插入之前被访问过?

0 个答案:

没有答案