用SQLAchemy 動態加入多個查詢條件

title: Dynamically add multiple condition into SQLAchemy query
tags: SQLAchemy, flask, python


用SQLAchemy 動態加入多個查詢條件

使用者輸入的查詢條件有多有少,數量不等,我們要怎麼動態的將這些查詢條件加入到我們的SQL指令當中呢?

假設我們是一個餐廳的查詢系統,使用者可以透過餐廳所在地點, 開放時間, 菜色來查詢喜歡的餐廳。使用者可能會只篩選地點,或是同事篩選三個,產生的組合就會有六種。我們不太可能寫六個SQL指令,將來如果查詢條件變多的話那不就要寫更多?

定義好我們的Model之後,我們寫一個get_restaurants的function,須入傳入constrains這個參數,constrains為一個dictionary的變數,記錄使用者的篩選條件(如my_constrains_1)。在get_restaurants有一個ands的變數,我們將constrains利用for迴圈配合and_這個SQLAchemy的函數一一寫入ands。最後把ands傳入filter當中即可完成動態建立篩選條件的需求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import and_
...
# 定義我們的Model
class Restaurant(db.Model):
__tablename__ = 'restaurant'
id = db.Column(db.String(64), primary_key=True)
name = db.Column(db.String(64))
city = db.Column(db.String(24))
open_hour = db.Column(db.String(64))
food_type = db.Column(db.String(64))
def __repr__(self):
return '<Restaurant %r>' % self.name


def get_restaurants(constrains={}):
ands = []
for key, value in constrains.items():
if key == "time":
ands.append(and_(Restaurant.open_hour.contains(value)))
elif key == "location":
ands.append(and_(Restaurant.city.contains(value)))
elif key == "food_type":
ands.append(and_(Restaurant.food_type.contains(value)))

return Restaurant.query.filter(*ands).limit(9)


my_constrains_1 = {"location": "台南", "time": "晚餐"}
restaurants = get_restaurants(my_constrains_1)

my_constrains_2 = {"location": "台北"}
restaurants = get_restaurants(my_constrains_2)

my_constrains_3 = {"location": "台東", "time": "晚餐", "food_type": "米苔目"}
restaurants = get_restaurants(my_constrains_3)

註:為了方便理解,範例有簡化,並非實際可執行的python程式