python - Sqlalchemy 为 parent 过滤父子表

标签 python sqlalchemy

我尝试搜索一些模型,因此我希望显示所有父对象的返回结果,其中父名称为“foo”或子名称为“foo”。

我有一个问题:

parents = Session.query(Parent).\
            join(Child_s3).\
            filter(Parent.name.ilike("%foo%")).\
            filter(Child_s3.name.ilike("%foo%")).\
            order_by(asc(Product.name))

和模型:

class Parent(BaseSO):
    __tablename__ = 'parents'
    id = Column(Integer, primary_key=True)
    name = Column(Unicode(100), nullable=False, unique=True)
    colours = relationship('Child_s3', secondary=Parent_images, backref='Parentc')

class Child_s3(BaseSO):
    __tablename__ = 'children'
    id = Column(Integer, primary_key=True)
    name = Column(Unicode)

Parent_images = Table(
    'Parent_images', BaseSO.metadata,
    Column('parent_id', Integer, ForeignKey('parents.id')),
    Column('child_id', Integer, ForeignKey('children.id'))
)

我的查询显示了名称为“foo”的父对象,但没有显示任何父对象,它们也有名为“foo”的子对象,任何人都可以帮助构建此查询以在两个表中搜索相应的父对象吗?

最佳答案

此代码显示如何使用显式连接或子查询获取结果:

import sqlalchemy as sa
from sqlalchemy import orm
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()


Parent_images = sa.Table(
    'Parent_images', Base.metadata,
    sa.Column('parent_id', sa.Integer, sa.ForeignKey('parents.id')),
    sa.Column('child_id', sa.Integer, sa.ForeignKey('children.id'))
)


class Parent(Base):
    __tablename__ = 'parents'
    id = sa.Column(sa.Integer, primary_key=True)
    name = sa.Column(sa.Unicode(100), nullable=False, unique=True)
    colours = orm.relationship('Child_s3', secondary=Parent_images, backref='parents')

    def __repr__(self):
        return 'Parent(name=%s)' % self.name

    __str__ = __repr__


class Child_s3(Base):
    __tablename__ = 'children'
    id = sa.Column(sa.Integer, primary_key=True)
    name = sa.Column(sa.Unicode)

    def __repr__(self):
        return 'Child_s3(name=%s)' % self.name

    __str__ = __repr__


if __name__ == '__main__':
    engine = sa.create_engine('sqlite:///')
    Base.metadata.drop_all(engine)
    Base.metadata.create_all(engine)
    Session = orm.sessionmaker(bind=engine)

    session = Session()
    for parent, child in [('boofoo', 'spam'), ('baz', 'foobar'), ('bar', 'quux')]:
        p1 = Parent(name=parent)
        session.add(p1)
        p1.colours.append(Child_s3(name=child))
    session.commit()

    print('Join')
    session = Session()
    q = (session.query(Parent)
                .join(Child_s3, Parent.colours)
                .filter(sa.or_(Parent.name.ilike('%foo%'),
                               Child_s3.name.ilike('%foo%'))))
    for p in q.all():
        print(p, p.colours)
    session.commit()
    print()

    print('Subquery')
    session = Session()
    q = (session.query(Parent)
                .filter(sa.or_(Parent.name.ilike('%foo%'),
                               Parent.colours.any(Child_s3.name.ilike('%foo%')))))
    for p in q.all():
        print(p, p.colours)
    session.commit()
    print()

连接查询

q = (session.query(Parent)
            .join(Child_s3, Parent.colours)
            .filter(sa.or_(Parent.name.ilike('%foo%'),
                           Child_s3.name.ilike('%foo%'))))

生成这条 SQL

SELECT parents.id AS parents_id, parents.name AS parents_name 
FROM parents JOIN "Parent_images" AS "Parent_images_1" ON parents.id = "Parent_images_1".parent_id JOIN children ON children.id = "Parent_images_1".child_id 
WHERE lower(parents.name) LIKE lower(?) OR lower(children.name) LIKE lower(?)

子查询

q = (session.query(Parent)
            .filter(sa.or_(Parent.name.ilike('%foo%'),
                            Parent.colours.any(Child_s3.name.ilike('%foo%')))))

生成此 SQL:

SELECT parents.id AS parents_id, parents.name AS parents_name            
FROM parents                                                                                                                        
WHERE lower(parents.name) LIKE lower(?) OR (EXISTS (SELECT 1                                                                        
FROM "Parent_images", children                                                                                                      
WHERE parents.id = "Parent_images".parent_id AND children.id = "Parent_images".child_id AND lower(children.name) LIKE lower(?)))

脚本从样本数据中产生这个输出:

Join
Parent(name=baz) [Child_s3(name=foobar)]
Parent(name=boofoo) [Child_s3(name=spam)]

Subquery
Parent(name=boofoo) [Child_s3(name=spam)]
Parent(name=baz) [Child_s3(name=foobar)]

关于python - Sqlalchemy 为 parent 过滤父子表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61346353/

相关文章:

python - 为图像塑造 Tensorflow/TFLearn 输入/输出的问题

python - 使用Python对按行和列分隔的数据进行数据处理

python - 使用 numpy 滚动最大值

python - 连接到 sqlalchemy 模型

python - SQLAlchemy 加密列而不在检索时自动解密

postgresql - 来自 jsonb 的 SQLAlchemy Pandas read_sql

python - odoo 12. 我无法对 Many2one 字段进行动态过滤

Python:为什么要 pickle ?

python - 使用 Cerberus 进行 SQLAlchemy 整个模型验证

python - 使用 SQLAlchemy 进行 Pyramid 异常记录 - 命令未提交