最近使用python+vue做一个web系统,碰到一个问题。
之前写代码的人,使用的是sqlalchemy提供的ORM框架来查询。查询时做了限定:前端必须选择所有条件才能查询。这样查询条件是固定了,代码也很好写。但是却给使用上带来了麻烦:比如前端有5个查询条件,有些时候想查询只满足1、2个条件下的内容,那怎么办呢?原来的代码肯定就不满足需求了。
当然,这个需求可以用if...else来写,把查询条件从全部为空、任意1个为空、任意2个为空……全不为空,这样全排列一下。每个条件对应一个固定的查询。如果查询条件少了还好说,多了的话,简直是灾难啊!
所以就想到使用动态拼SQL的方式,先写一个这样的语句:
sql_str = "select * from myTable where 1=1"
之后依次根据查询条件是否为空,进行拼接,就像这样:
if p_id:
sql_str = sql_str + " and id = p_id"
但是有个问题啊,p_id是个参数,这样在sql字符串里面直接写p_id会被当做字符串,无法获取到参数。
那么如果我直接写一个可以执行的sql,在python下会这么写:
sql_str = "select * from myTable where 1=1 and id = %s" % p_id
所以,不仅要把sql字符串里面的查询条件拼接上,还要把参数也给带上才行。如何带上?通过搜索,发现python2.6之后其实比较提倡使用format来格式化参数,因此上述语句可以改成这样:
sql_str = "select * from myTable where 1=1 and id = {p_id}".format(p_id)
而且,我们还可以通过字典来设置参数,就像这样:
# 通过字典设置参数
site = {"name": "菜鸟教程", "url": "www.runoob.com"}
print("网站名:{name}, 地址 {url}".format(**site))
因此我有了思路:还是按照之前的方式来拼sql字符串,同时把对应的参数加到参数字典里,不就行了吗!
因此,下面给出连接数据库开始,直到完成查询的代码:
#! -*- coding:utf8 -*-
import sqlalchemy
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
engine = create_engine("mysql+pymysql://root:root@localhost:3306/mydatabase?charset=utf8mb4")
Session_class = sessionmaker(bind=engine)
session = Session_class()
session.execute('use mydatabase;')
hash = {} #字典参数,初始为空
p_id = 1
m_id = ''
name = 'my'
# 上面是三个查询条件,其中两个为空
sql_str = "select * from myTable where 1=1"
if p_id:
sql_str = sql_str+" and p_id = {p_id}"# id, 查询时要精确匹配
hash['p_id'] = p_id
if m_id:
sql_str = sql_str+" and m_id = {m_id}"
hash['m_id'] = m_id
if name:
sql_str = sql_str + " and name like '%{name}%'"#名字,需要支持模糊查询
hash['name'] = name
result = session.execute(sql_str.format(**hash))
for r in result:
print(r)
当然,我还是不知道如何使用ORM框架,来实现这种效果,所以就只能拼SQL啦,可能并不是最好的方式,但起码实现了想要的功能。
如果你知道如何使用sqlalchemy提供的ORM框架来写的话,欢迎告诉我哦!
PS: 自己找到了如何用框架来写,原理差不多,具体见下文:
Python SQLAlchemy 不确定条件查询
https://www.jianshu.com/p/a33f48387efa
网友评论