【问题标题】:Equivalent of models.Manager for SqlAlchemySqlAlchemy 的 models.Manager 的等价物
【发布时间】:2011-09-30 05:00:07
【问题描述】:

我正在使用 SQLAlchemy,而我喜欢 Django ORM 是我可以实现的管理器来覆盖对象的初始查询。

SQLAlchemy 中是否存在类似的东西?当我执行以下操作时,我想始终排除具有“visible = False”的项目:

session.query(BlogPost).all()

有可能吗?

谢谢!

【问题讨论】:

    标签: python django sqlalchemy


    【解决方案1】:

    编辑:原始版本几乎可以使用。以下版本确实有效。

    听起来您正在尝试将查询实体安排为 SELECT table.* FROM table 以外的其他内容。在sqlalchemy中,你可以map any "selectable"到一个类;不过,有一些警告;如果 selectable 不是表,则插入数据可能会很棘手。像这样的东西接近一个可行的解决方案。您可能确实希望有一个映射到允许插入的常规表,所以第一部分是一个完全正常的表、类和映射器。

    blog_post_table = Table("blog_posts", metadata,
        Column('id', Integer, primary_key=True),
        Column('visible', Boolean, default=True),
        ...
    )
    
    class BlogPost(object):
        pass
    
    blog_post_mapper = mapper(BlogPost, blog_post_table)
    

    或者,如果您使用的是声明式扩展,那么它就是一个

    class BlogPost(Base):
        __tablename__ = 'blog_posts'
        id = Column(Integer, primary_key=True)
        visible = Column(Boolean, default=True)
    

    现在,我们需要一个 select 表达式来表示可见帖子。

    visible_blog_posts_expr = sqlalchemy.sql.select(
            [BlogPost.id,
             BlogPost.visible]) \
        .where(BlogPost.visible == True) \
        .alias()
    

    或者,由于命名所需查询的所有列很繁琐(更不用说违反 DRY),您可以使用与 session.query(BlogPost) 相同的构造并提取“语句”。不过,您实际上并不希望它绑定到会话,因此请直接调用该类。

    visible_blog_posts_expr = \
        sqlalchemy.orm.Query(BlogPost) \
        .filter(BlogPost.visible == True) \
        .statement \
        .alias()
    

    我们也映射它。

    visible_blog_posts = mapper(BlogPost, visible_blog_posts_expr, non_primary=True)
    

    然后您可以使用visible_blog_posts 映射器而不是BlogPosts 和Session.query,您仍然会得到BlogPost,它可以正常更新和保存。

    posts = session.query(visible_blog_posts).all()
    assert all(post.visible for post in posts)
    

    对于这个特定示例,显式使用 mapper 和声明性扩展之间没有太大区别,您仍然必须为非主映射调用 mapper。充其量,它允许您输入SomeClass.colname 而不是some_table.c.colname(或SomeClass.__table__.colname,或BlogPost.metadata.tables[BlogPost.__tablename__] 或...等等)。

    我在原始示例中犯的错误,现在已更正。我在调用 sqlalchemy.sql.select 时遗漏了一些缺少的[],它期望列是按顺序排列的。当使用select 语句到mapper 时,sqlalchemy 坚持该语句是别名,以便它可以命名为(SELECT .... ) AS some_subselect_alias_5

    【讨论】:

    • 我正在使用声明方式,你能用它更新你的例子吗? (我不能让它工作:/)顺便说一句,哪个最好?声明式还是你的?
    • 两者都不是更好,但声明式肯定更方便;我更喜欢它。
    • 完美!感谢作为声明方式和指示的更改! :) 现在可以了。是否可以在我的表中使用新的 visible_blog_posts 而不是 OneToMany 键? (就像我的博客模型中的 get_all_blog_posts)
    • 我不太明白你在问什么。您应该提出一个新问题,以便详细说明。
    【解决方案2】:

    你可以这样做,例如

    session.query(BlogPost).filter_by(visible=True)
    

    它应该只为您提供所需的帖子。

    【讨论】:

      猜你喜欢
      • 2010-12-20
      • 2016-12-20
      • 2018-07-25
      • 2020-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-08
      相关资源
      最近更新 更多