我正在尝试从 SQLAlchemy 中的多个连接表加载列的子集,但无法弄清楚魔术语法。
这是我正在尝试做的一个简单示例。它导致错误(如下):
from sqlalchemy import create_engine
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, load_only
Base = declarative_base()
class Table1(Base):
__tablename__ = 'table1'
table1_id = Column(Integer, primary_key=True)
table1_val = Column(String)
r1 = relationship('Table2', backref = 'r2')
class Table2(Base):
__tablename__ = 'table2'
table2_id = Column(Integer, ForeignKey('table1.table1_id'), primary_key=True)
table2_val = Column(String)
from sqlalchemy.orm import sessionmaker
some_engine = create_engine('postgresql://scott:tiger@localhost/')
Session = sessionmaker(bind=some_engine)
session = Session()
query = session.query(Table1).join(Table2).options(load_only('table1_val','table2_val'))
Run Code Online (Sandbox Code Playgroud)
ArgumentError: 在此查询的映射实体 Mapper|Table1|table1 上找不到名为“table2_val”的属性。
如何从这些多个表中挑选列?
问题已在 [ https://bitbucket.org/zzzeek/sqlalchemy/issues/3679/multiple-load_only-in-queryoptions-ignore]得到解答
这是更正后的代码:
from sqlalchemy import create_engine
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import joinedload, Load, relationship, load_only
Base = declarative_base()
class Table1(Base):
__tablename__ = 'table1'
global_id = Column(Integer, primary_key=True)
table1_val1 = Column(String)
table1_val2 = Column(String)
r1 = relationship('Table2', backref = 'r2')
class Table2(Base):
__tablename__ = 'table2'
global_id = Column(Integer, ForeignKey('table1.global_id'), primary_key=True)
table2_val1 = Column(String)
table2_val2 = Column(String)
from sqlalchemy.orm import sessionmaker
some_engine = create_engine('sqlite://')
Base.metadata.create_all(some_engine)
Session = sessionmaker(bind=some_engine)
session = Session()
session.add(Table1(table1_val1='1val1',table1_val2='1val2',r1=[Table2(table2_val1='2val1', table2_val2='2val2')]))
session.commit() # expires the attribute from the session
query = session.query(Table1).options(
# note that the 'load_only()' is applied to the 'joinedload' path, not
# put on its own Load() path
joinedload('r1',innerjoin=True).load_only('table2_val1'),
Load(Table1).load_only('table1_val1'))
foo = query.all()
assert 'table1_val2' not in foo[0].__dict__
assert 'table2_val2' not in foo[0].r1[0].__dict__
Run Code Online (Sandbox Code Playgroud)