为了账号安全,请及时绑定邮箱和手机立即绑定

Python postgreSQL sqlalchemy 查询一个 DATERANGE 列

Python postgreSQL sqlalchemy 查询一个 DATERANGE 列

慕码人2483693 2021-09-14 20:59:41
我有一个预订系统,并将预订的日期范围保存在 DATERANGE 列中:booked_date = Column(DATERANGE(), nullable=False)我已经知道我可以使用booked_date.lower或访问实际日期booked_date.upper例如,我在这里这样做:for bdate in room.RoomObject_addresses_UserBooksRoom:     unaviable_ranges['ranges'].append([str(bdate.booked_date.lower),\    str(bdate.booked_date.upper)])现在我需要按给定的日期范围过滤我的预订。例如,我想查看 01.01.2018 和 10.01.2018 之间的所有预订。通常它很简单,因为日期可以这样比较: date <= other date但是如果我用 DATERANGE 来做:the_daterange_lower = datetime.strptime(the_daterange[0], '%d.%m.%Y')the_daterange_upper = datetime.strptime(the_daterange[1], '%d.%m.%Y')bookings = UserBooks.query.filter(UserBooks.booked_date.lower >= the_daterange_lower,\UserBooks.booked_date.upper <= the_daterange_upper).all()我收到一个错误:AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object associated with UserBooks.booked_date has an attribute 'lower'编辑我找到了一个带有有用范围运算符的工作表,看起来有更好的选择来做我想做的事情,但为此我需要以某种方式创建一个range variable,但 python 不能这样做。所以我还是很困惑。在我的数据库中,我的 daterange 列条目如下所示:[2018-11-26,2018-11-28)编辑我正在尝试使用本机 SQL 而不是 sqlalchemy,但我不明白如何创建 daterange 对象。bookings = db_session.execute('SELECT * FROM usersbookrooms WHERE booked_date && [' + str(the_daterange_lower) + ',' + str(the_daterange_upper) + ')')
查看完整描述

1 回答

?
弑天下

TA贡献1818条经验 获得超8个赞

查询


the_daterange_lower = datetime.strptime(the_daterange[0], '%d.%m.%Y')

the_daterange_upper = datetime.strptime(the_daterange[1], '%d.%m.%Y')


bookings = UserBooks.query.\

    filter(UserBooks.booked_date.lower >= the_daterange_lower,

           UserBooks.booked_date.upper <= the_daterange_upper).\

    all()

可以使用“范围由”操作符来实现<@。为了传递正确的操作数,您必须创建一个 的实例psycopg2.extras.DateRange,它代表daterangePython 中的 Postgresql值:


the_daterange_lower = datetime.strptime(the_daterange[0], '%d.%m.%Y').date()

the_daterange_upper = datetime.strptime(the_daterange[1], '%d.%m.%Y').date()


the_daterange = DateRange(the_dateranger_lower, the_daterange_upper)


bookings = UserBooks.query.\

    filter(UserBooks.booked_date.contained_by(the_daterange)).\

    all()

请注意,属性lower和upper是psycopg2.extras.Range类型的一部分 。SQLAlchemy 范围列类型不提供此类,如您的错误状态。


如果您想使用原始 SQL 并传递日期范围,您也可以使用相同的DateRange对象来传递值:


bookings = db_session.execute(

    'SELECT * FROM usersbookrooms WHERE booked_date && %s',

    (DateRange(the_daterange_lower, the_daterange_upper),))

如果您想,您也可以手动构建文字:


bookings = db_session.execute(

    'SELECT * FROM usersbookrooms WHERE booked_date && %s::daterange',

    (f'[{the_daterange_lower}, {the_daterange_upper})',))

诀窍是在 Python 中构建文字并将其作为单个值传递 - 一如既往地使用占位符。它应该避免任何 SQL 注入的可能性;唯一可能发生的事情是文字对于 a 的语法无效daterange。或者,您可以将边界传递给范围构造函数:


bookings = db_session.execute(

    'SELECT * FROM usersbookrooms WHERE booked_date && daterange(%s, %s)',

    (the_daterange_lower, the_daterange_upper))

总而言之,使用 Psycopg2Range类型并让它们处理细节更容易。


查看完整回答
反对 回复 2021-09-14
  • 1 回答
  • 0 关注
  • 200 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信