我有一些看起来非常像这样的代码:
import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base
engine = sa.create_engine('sqlite:///:memory:', echo=True)
Base = declarative_base()
class OneThing(Base):
__tablename__ = 'one'
id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.Text)
value = sa.Column(sa.Text)
class OtherThing(Base):
__tablename__ = 'other'
id = sa.Column(sa.Integer, primary_key=True)
some_deal = sa.Column(sa.Text)
other_deal = sa.Column(sa.Text)
Base.metadata.create_all(engine)
session = sa.orm.sessionmaker(bind=engine)()
one = OneThing()
one.id = 42
one.name = 'hi'
one.value = 'roscivs'
session.add(one)
other = OtherThing()
other.id = 42
other.some_deal = 'brown'
other.other_deal = 'and sticky'
session.add(other)
session.commit()
现在,我可以运行以下内容:
for row in session.query(OneThing).outerjoin(OtherThing, OneThing.id == OtherThing.id):
print(row)
它会打印一行。显然我没有__repr__
所以它只是打印出非常难看的默认repr。但是,假设我想要other_deal
值,所以我输入了print(row.other_deal)
。
我收到以下错误:
Traceback (most recent call last):
File "test.py", line 43, in <module>
print(row.other_deal)
AttributeError: 'OneThing' object has no attribute 'other_deal'
事实上你可以看到发出的SQL并不是我想要的:
SELECT one.id AS one_id, one.name AS one_name, one.value AS one_value
FROM one LEFT OUTER JOIN other ON one.id = other.id
是做外连接...但它只返回one
表中的列。我希望one
和 other
。我怎么做到的?
我已经尝试了add_entity
,但这并没有达到我想要的效果。
我是如何从两个模型中获取列的? (注意,我不能在两个表之间添加ForeignKey
关系)
答案 0 :(得分:5)
首先从其他一些事情开始,我们将回答您的实际问题。
首先,declarative_base
提供了一个关键字参数构造函数,所以不是这样:
one = OneThing()
one.id = 42
one.name = 'hi'
one.value = 'roscivs'
你可以写:
one = OneThing(id=42, name='hi', value='roscivs')
第二:假设两个表之间存在数据库关系,您可以使用relationship
定义来通知sqlalchemy
模型之间的关系。在这里,我假设从id
列到id
列有一个ForeignKey,它是一对一的关系:
class OtherThing(Base):
...
id = sa.Column(sa.Integer, sa.ForeignKey(OneThing.id), primary_key=True)
...
one_thing = sa.orm.relationship(OneThing, backref=sa.orm.backref('other_thing', uselist=False))
在这种情况下,您可以按如下方式编写当前查询,sqlalchemy
将确定连接条件:
query = session.query(OneThing).outerjoin(OtherThing)
最后,让我们在结果中包含相关数据。有多个选项,但从您拥有的内容开始,您可以查询OneThing
(仅限),然后导航上面定义的关系:
query = session.query(OneThing).outerjoin(OtherThing)
for one in query:
print(one)
print(one.other_thing.other_deal)
另一种选择是同时查询两个模型,但请注意,结果行包含(OneThing, OtherThing)
的元组:
query = session.query(OneThing, OtherThing).outerjoin(OtherThing)
for one, oth in query:
print(one)
print(oth)
另一种选择是仅查询列的子集:
query = session.query(OneThing.name, OtherThing.other_deal).outerjoin(OtherThing)
for row in query:
print(row)
# ('hi', 'and sticky')