如何在Flask-SQLAlchemy查询中用case when优化filter_by冗余代码?
Flask-SQLAlchemy 重复查询代码优化方案
核心思路
SQLAlchemy 的查询为惰性链式构造模式,只有调用执行方法(all()/first()等)时才会生成SQL访问数据库,因此可以把公共查询逻辑抽离复用,仅对差异化的筛选条件做单独判断,完全消除重复代码。
原代码隐含问题修正说明
当前代码中获取TestDate时,first()返回的是单行结果元组,而非直接的日期值,直接和字符串比较会触发类型错误,需要先取出元组的第一个元素拿到实际的test_date值。另外or_(TestCodeName.code.contains(search))仅包含单个筛选条件,or_语法无实际作用,可以直接删除。
优化后代码
写法1:抽离公共查询(扩展性更强,适合后续需要追加更多差异化条件的场景)
somewords = args.get('somewords') search = "%{}%".format(somewords) # 修正日期取值逻辑 test_date = db.session.query(TestProject.test_date).filter(TestProject.id == id).first()[0] # 构造公共查询逻辑 base_query = db.session.query(TestCodeName.code) \ .distinct(TestCodeName.code, TestCodeName.type) \ .filter(TestCodeName.code.contains(search)) # 仅追加差异化的type筛选条件 if test_date >= '2021-01-01': base_query = base_query.filter_by(type='Type_One') else: base_query = base_query.filter_by(type='Type_Two') # 执行查询获取结果 test_code = base_query.all()
写法2:三元表达式简化(更简洁,适合当前单条件判断的场景)
somewords = args.get('somewords') search = "%{}%".format(somewords) test_date = db.session.query(TestProject.test_date).filter(TestProject.id == id).first()[0] # 提前判断type取值,直接传入查询即可 type_val = 'Type_One' if test_date >= '2021-01-01' else 'Type_Two' test_code = db.session.query(TestCodeName.code) \ .distinct(TestCodeName.code, TestCodeName.type) \ .filter_by(type=type_val) \ .filter(TestCodeName.code.contains(search)) \ .all()
优化收益
- 公共逻辑仅需维护一次,后续调整查询字段、去重规则、模糊匹配逻辑时只需要修改一处,降低维护成本
- 没有额外的性能损耗,和原代码生成的执行SQL完全一致
- 代码层级更清晰,差异化逻辑和公共逻辑分离,可读性更高
内容的提问来源于stack exchange,提问作者Elsa
相关产品推荐
相关产品推荐

