一个项目中需要会有多个字段以多个查询条件,
并且这些条件是不固定的
DEMO
# 数据库模型
class Customs(db.Model):
__tablename__ = 'customs'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64))
phone = db.Column(db.String(64))
# 视图中使用
@app.route('/table/', methods=['GET', 'POST'])
def customs():
# 接收查询的字段名称 可能是name/phone等变量
field = request.args.get('field')
# 假设 field 接收到的值是 'name' , 正常的查询是这样的
# customs = Customs.name.query.all()
# 我想实现根据接收到的变量进行查询
# 类似这种方式
if field:
customs = Customs[field].query.all()
# 这样写会报错
# >>>TypeError: '_BoundDeclarativeMeta' object is not subscriptable
一番查询之后,找到这样一个解决方案
这个方案需要把所有可能的条件全部if else枚举出来 再传给filter
并不是理想的解决方案
开发中,我们经常会碰到根据传入的参数构造查询条件进行查询。比如
- 如果接收到非 0 的
cat_id
,需要限制cat_id
等于 0- 如果接收到非 0 的 price,需要限制 price 等于传入的 price
- 如果接收到非 0 的
min_price
,需要限制 price 大于等于min_price
- 如果接收到非 0 的
max_price
,需要限制 price 小于等于max_price
我们就可以编写类似的代码
# 请求参数,这里只是占位,实际由用户提交的请求决定 params = {'cat_id': 1} conditions = [] if params.get('cat_id', 0): conditions.append(Book.cat_id == params['cat_id']) if params.get('price', 0): conditions.append(Book.price == params['price']) if params.get('min_price', 0): conditions.append(Book.price >= params['min_price']) if params.get('max_price', 0): conditions.append(Book.price <= params['max_price']) books = session.query(Book).filter(*conditions).all() print([v.to_dict() for v in books]) 复制代码
结果
[{'id': 1, 'cat_id': 1, 'name': '生死疲劳', 'price': Decimal('40.40')}, {'id': 2, 'cat_id': 1, 'name': '皮囊', 'price': Decimal('31.80')}] 复制代码
OR 查询类似,将列表解包传给
or_()
即可。
这个帖子还提有另一种解决方案
当然,如果都是等值查询的话,比如只有这两种情况
- 如果接收到非 0 的
cat_id
,需要限制cat_id
等于 0- 如果接收到非 0 的 price,需要限制 price 等于传入的 price
可以使用字典的解包给
filter_by()
传参# 请求参数,这里只是占位,实际由用户提交的请求决定 params = {'price': 31.1} condition_dict = {} if params.get('cat_id', 0): condition_dict['cat_id'] = params['cat_id'] if params.get('price', 0): condition_dict['price'] = params['price'] books = session.query(Book) \ .filter_by(**condition_dict) \ .all() print([v.to_dict() for v in books]) 复制代码
结果
[{'id': 6, 'cat_id': 3, 'name': '时间简史', 'price': Decimal('31.10')}]
如帖子所说,这种方式只能解决等值(=)的情况
而实际业务中有=、>=、<=、!= 、%like%等情况
如何现实这种动态字段查询?