如何在 SQLAlchemy 对象实例中查询一对多关系?

问题描述 投票:0回答:2

假设我有以下内容(在 Python 3 和 SQLAlchemy 中):

class Book(Base):
    id = Column(Integer, primary_key=True)
    chapters = relationship("Chapter", backref="book")

class Chapter(Base):
    id = Column(Integer, primary_key=True)
    name = Column(String)
    book_id = Column(Integer, ForeignKey(Book.id))

def check_for_chapter(book): 
    # This is where I want to check to see if the book has a specific chapter.
    for chapter in book.chapters:
        if chapter.name == "57th Arabian Tale"
            return chapter
    return None

这感觉像是一种“非惯用”方法,因为它似乎不太可能利用数据库来搜索给定的章节。在最坏的情况下,似乎将对数据库进行

n
调用来检查章节标题,尽管我对 SQLAlchemy 的有限理解表明这可以配置。我不知道是否有一种方法可以直接针对已获取的对象的关系发起查询?如果是这样,如何做到这一点?

python python-3.x sqlalchemy
2个回答
6
投票

如果您想获取一本特定书籍的特定章节,下面的代码应该在一个 SQL 语句中完成:

book = ...  # get book instance 

chapter = (
    session.query(Chapter)
    .with_parent(book)
    .filter(Chapter.name == "57th Arabian Tale")
    .one()
)

例如,如果您只有书名和章节标题,您可以这样做:

chapter = (
    session.query(Chapter)
    .join(Book)
    .filter(Book.name == "One Thousand and One Nights")
    .filter(Chapter.name == "57th Arabian Tale")
    .one()
)

另请阅读使用联接进行查询以及SQLAlchemy文档的其余部分。


0
投票

接受答案的V2.x兼容代码:

from sqlalchemy import select
from sqlalchemy.orm import with_parent
...

book = ...  # get book instance 

with Session(engine) as session:
    stmt = select(Chapter)
           .where(
               and_(
                   with_parent(book, Book.chapters),
                   Chapter.name == "57th Arabian Tale"
               )
           )
    chapter = session.scalars(stmt).one()
© www.soinside.com 2019 - 2024. All rights reserved.