如何在sqlalchemy中加入两个ORM表,但要将两列都归还?

Way*_*ner 1 python orm sqlalchemy

我有一些看起来非常像这样的代码:

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()
Run Code Online (Sandbox Code Playgroud)

现在,我可以运行以下内容:

for row in session.query(OneThing).outerjoin(OtherThing, OneThing.id == OtherThing.id):
    print(row)
Run Code Online (Sandbox Code Playgroud)

它会打印一行.显然我没有,__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'
Run Code Online (Sandbox Code Playgroud)

事实上你可以看到发出的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
Run Code Online (Sandbox Code Playgroud)

做外连接...但它只是从返回的列one表.我想one other.我怎么做到的?

我试过了add_entity,但那并没有做我想要的.

如何从两个模型中获取列的任何线索?(注意,我不能ForeignKey在两个表之间添加关系)

van*_*van 7

首先从其他一些事情开始,我们将回答您的实际问题.

首先,declarative_base提供一个关键字参数构造函数,所以代替:

one = OneThing()
one.id = 42
one.name = 'hi'
one.value = 'roscivs'
Run Code Online (Sandbox Code Playgroud)

你可以写:

one = OneThing(id=42, name='hi', value='roscivs')
Run Code Online (Sandbox Code Playgroud)

第二:假设两个表之间存在数据库关系,您可以使用该relationship定义来通知sqlalchemy模型之间的关系.这里我假设id列之间有一个ForeignKey id,它是一对一的关系:

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))
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您可以编写当前查询,如下所示,sqlalchemy并将确定连接条件:

query = session.query(OneThing).outerjoin(OtherThing)
Run Code Online (Sandbox Code Playgroud)

最后,让我们在结果中得到相关数据.有多个选项,但从您可以查询OneThing(仅)开始,然后导航上面定义的关系:

query = session.query(OneThing).outerjoin(OtherThing)
for one in query:
    print(one)
    print(one.other_thing.other_deal)
Run Code Online (Sandbox Code Playgroud)

另一种选择是同时查询两个模型,但请注意结果行包含以下元组(OneThing, OtherThing):

query = session.query(OneThing, OtherThing).outerjoin(OtherThing)
for one, oth in query:
    print(one)
    print(oth)
Run Code Online (Sandbox Code Playgroud)

另一种选择是仅查询列的子集:

query = session.query(OneThing.name, OtherThing.other_deal).outerjoin(OtherThing)
for row in query:
    print(row)
# ('hi', 'and sticky')
Run Code Online (Sandbox Code Playgroud)