使用SQLAlchemy进行组合分页查询

本文探讨了在Python中利用SQLAlchemy进行灵活的组合查询及安全处理方法,并介绍了如何实现高效的分页查询。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

最近在写web端的时候经常会遇到一个问题,查询数据的时候需要组合条件来查询,并且需要对结果做分页,在网上找了好久,都是到处“借鉴”,无奈之下只能自己研究,这里吧研究的结果记录下来

拼SQL来做组合查询

拼SQL是一个最基本的方式,总体的执行难度也不大,不过容易引起SQL注入。但是拼的方式有点讲究,不同的拼法对后续的影响也是不一样的。

  • Python的语法进行格式化

Python中,字符串格式化最方便的就是通过format()方法来进行字符串的替换,比如需要拼一句SQL可以用下列的方式:

"select * from photo_info where {0} {1}".format("a=1", " and b=2")

这种方式应该说是最原始的方式了,比较容易引起SQL注入。而且查询条件复杂之后,整个句式看起来会有点不舒服。

目前主流的方式操作数据库都是使用ORM的框架来处理,比如SQLAlchemy这种。

使用SQLAlchemy来做组合查询

首先必须说明,SQLAlchemy是不支持组合查询时动态删除元素的,举个例子,比如你有四个查询条件,如果其中一个字段的值为空,那么这个空的值依然会按照空去做SQL查询,而不会删了这个字段,用剩下的3个字段去查询。

ORM:
photoinfo.filter(PhotoDB.PhotoInfo.category == category)
.filter(PhotoDB.PhotoInfo.is_banner == is_banner)
.filter(PhotoDB.PhotoInfo.photo_desc.like("%{0}%".format(photo_desc))).filter(PhotoDB
.PhotoInfo.photo_title.like("%{0}%".format(photo_title))).all()

SQL:
select * from photo_info where category = "category" and is_banner = "is_banner" and photo_desc = "photo_desc" and photo_title = "photo_title"

上面的示例,必须要4个字段有值,如果其中一个没有值,SQL就会变成这样:
select * from photo_info where category = "" and is_banner = "is_banner" and photo_desc = "photo_desc" and photo_title = "photo_title"
与我要的结果不一样,我想要的是这样:
select * from photo_info where is_banner = "is_banner" and photo_desc = "photo_desc" and photo_title = "photo_title"

SQLAlchemy还是有一个比较优雅的实现方式,有点类似拼SQL,但是整体看起来逻辑很清晰。

    if category:
        photoinfo = photoinfo.filter(PhotoDB.PhotoInfo.category == category)
    if is_banner:
        photoinfo = photoinfo.filter(PhotoDB.PhotoInfo.is_banner == is_banner)
    if photo_desc:
        photoinfo = photoinfo.filter(PhotoDB.PhotoInfo.photo_desc.like("%{0}%".format(photo_desc)))
    if photo_title:
        photoinfo = photoinfo.filter(PhotoDB.PhotoInfo.photo_title.like("%{0}%".format(photo_title)))
    photos = photoinfo.all()

这样看起来就很清晰,能够实现我想要的效果,并且SQLAlchemySQL注入做了保护措施,不会引发安全问题。

分页查询

分页查询的逻辑很简单,用SQLAlchemy实现起来也非常简单。

  • 使用pagenate

如果要使用pagenate来处理分页,那么查询的方式必须继承与BaseQuery,否则会报错找不到此方法,使用方式接上例如下所示:

photos = photoinfo.pagination(1, 10)

那么,只要迭代photos变量的itemsphotos.items即可获得查询结果

  • 使用offset()limit()
    offset是查询的偏移量,而limit限制了返回的条数,接上例实现方式如下:
    photos = photoinfo.limit(PAGESIZE).offset((int(current_page) - 1) * PAGESIZE)

总结

组合条件查询和分页都有多种实现方式,我们应该选择看起来逻辑清晰并且安全的方式来编码,这样对日后的维护会非常友好

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

点点寒彬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值