SQLAlchemy - 将文本查询与过滤器结合

4 投票
2 回答
4541 浏览
提问于 2025-04-16 14:38

我正在使用SA 0.6.6Python 2.66Postgres 8.3

我有一些查询需要进行比较复杂的安全检查,这可以通过一个WITH RECURSIVE查询来处理。我想做的是把一个文本查询和一个查询对象结合起来,这样我就可以根据需要应用过滤条件。

我最开始的想法是把我的文本查询作为一个子查询,然后把它和用户的查询及过滤条件结合起来。不幸的是,这样做并没有成功。

subquery = session.query(sharedFilterAlias).\
                   from_statement(sharedFilterQuery).subquery()

这导致了这个错误:

AttributeError: 'Annotated_TextClause' object has no attribute 'alias'

有没有办法把文本查询和SQLAlchemy的查询对象结合起来呢?

2 个回答

2

我在使用子查询时,发现把 select_from 方法和查询方法连起来用效果不错。像这样的写法可能会有效果;不过因为我对你的数据模型和你想生成的SQL语句了解不多,所以不能完全确定。

results = session.query(sharedFilterAlias).select_from(sharedFilterQuery).all()
7

过了一段时间没有人回答我的问题,我在SA Google Group上发了帖子,结果Michael Bayer本人给了我正确的方向。

解决办法是把我的文本查询转换成SA的文本子句。然后用这个子句配合in_操作符。下面是最终的代码示例:

sharedFilterQuery = '''WITH    RECURSIVE
        q AS
        (
        SELECT  h.*
        FROM    "Selection"."FilterFolder" h
        join "Selection"."Filter" f
        on f."filterFolderId" = h.id
        WHERE   f.id = :filterId 
        UNION
        SELECT  hp.*
        FROM    q
        JOIN    "Selection"."FilterFolder" hp
        ON      hp.id = q."parentFolderId"
        )
SELECT  f.id
FROM    "Selection"."Filter" f
where f.id = :filterId and
(f."createdByUserId" = 1 or
exists(select 1 from q where "isShared" = TRUE LIMIT 1))
'''

inClause = text(sharedFilterQuery,bindparams=[bindparam('filterId',filterId)])

f = session.query(Filter)\
.filter(Filter.description == None)\
.filter(Filter.id.in_(inClause)).first()

撰写回答