在Sqlalchemy的查詢中新共享filter

songofhawk發表於2022-03-07

使用Python做web開發,OR Mapping的部分,通常會用到Sqlalchemy,它是一個相對重量級的資料庫封裝層,提供了豐富的呼叫介面。

用Sqlalchemy實現查詢是相當簡單的,比如下面的SQL:

select * from table_a where col1=3 and col2='abc'

寫成程式碼就是:

TableA.query.filter(TableA.col1==3).filter(TableA.col2=='abc')

但有的時候,我們會發現程式碼中經常有兩條或多條查詢,它們的條件是一模一樣的,只有select後面有差別,比如我還想取個總數:

select count(*) from table_a where col1=3 and col2='abc'
db.session.query(func.count('*').filter(TableA.col1==3).filter(TableA.col2=='abc')

這就很彆扭了,同樣的程式碼被重複編寫,如果這個條件複雜,需要經過各種邏輯判斷拼接的話,就更加難受:每條拼接語句都要copy一次,程式碼的壞味道快溢位螢幕了~~~

有沒有辦法讓它們共享同一個filter呢?還有有的,可以用list巢狀表示式,先把filter儲存起來,最後再一起傳給query物件:

all_filters = [
    TableA.col1==3,
    TableA.col2=='abc'
]

records = TableA.query.filter(*all_filters).all()

count = db.session.query(
    func.count('*')
).filter(
    *all_filters
).first()

網上描述這個問題的文章不多,google了半天,才找到一個答案:Apply condition based multiple filters in SQLAlchemy query

問題是它還有個錯誤,把*all_filters寫成了**all_filters,害的我差點放棄。

相關文章