我正在使用SQLAlchemy ORM进行Flask项目,我想在一个急切加载的模型中加入,但这会导致两个连接到同一个中间模型。如果您运行下面的代码,您将在生成的SQL中看到Author模型和Book模型之间有两个连接。如果删除lazy=joined
位,则生成的sql是完美的。
我不知道我做错了什么或者这是设计的。在这种情况下,如何在保持joinload的同时让SQLAlchemy发出正确的SQL?
注意:我已经尝试过使用MySQL和SQLite,并且这两种dbs都会发生这种情况。
from sqlalchemy import create_engine, Integer, String, Column
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship
engine = create_engine('sqlite:///:memory:', echo=True)
Session = sessionmaker(bind=engine)
Base = declarative_base()
from sqlalchemy import create_engine, Integer, String, Column
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship
engine = create_engine('sqlite:///:memory:', echo=True)
Session = sessionmaker(bind=engine)
Base = declarative_base()
class Author(Base):
__tablename__ = 'authors'
id = Column(Integer, primary_key=True)
name = Column(String)
pseudo = Column(String)
books = relationship("Book", lazy='joined')
def __repr__(self):
return "<User(name='%s', fullname='%s', password='%s')>" % (
self.name, self.fullname, self.password)
class Book(Base):
__tablename__ = 'books'
id = Column(Integer, primary_key=True)
author_id = Column(Integer, ForeignKey('authors.id'))
name = Column(String)
user = relationship("Author", back_populates="books")
pages = relationship("Page")
class Page(Base):
__tablename__ = 'pages'
id = Column(Integer, primary_key=True)
book_id = Column(Integer, ForeignKey('books.id'))
text = Column(String)
book = relationship("Book", back_populates="pages")
Base.metadata.create_all(engine)
session = Session()
print(str(session.query(Author).outerjoin(Author.books, Page)))
答案 0 :(得分:1)
这是设计 - 阅读The Zen of Joined Eager Loading:
了解使用
Query.join()
来改变查询结果的区别至关重要,joinedload()
需要花费很长时间才能不更改结果查询,而是隐藏渲染连接的效果,只允许相关对象存在。
sqlalchemy中存在多个有些类似的问题,但无法找到符合该法案的问题。
如果您手动添加联接,并希望使用它来急切加载关系,则需要contains_eager()
:
session.query(Author).\
outerjoin(Author.books, Book.pages).\
options(contains_eager(Author.books).contains_eager(Book.pages))
请注意,关系定义Author.books
和Book.pages
似乎缺少back_populates=
参数。