且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

SQLAlchemy在时隙中获取行

更新时间:2023-02-26 20:43:08

我认为对于sqlite和postgres,您都不能直接在ORM中执行此操作,但是sqlalchemy允许您使用自定义SQL构造和编译扩展

I don't think you'll be able to do this directly in the ORM for both sqlite and postgres, but sqlalchemy lets you extend it in a cross-dialect way with Custom SQL Constructs and Compilation Extension.

此代码段可能不是确实是对的,因为我用一些不同的模型对其进行了破解并为此进行了翻译,但是我得到了一些非常接近的东西,可以正确地渲染postgres SQL:

This snippet might not be exactly right because I hacked at it with some different models and translated it over for this, but I got something very close to render the postgres SQL correctly:

from sqlalchemy import func
from sqlalchemy.sql import expression
from sqlalchemy.types import DateTime
from sqlalchemy.ext.compiler import compiles

class durationnow(expression.FunctionElement):
    type = DateTime()
    name = 'durationnow'

@compiles(durationnow, 'sqlite')
def sl_durationnow(element, compiler, **kw):
    return compiler.process(
        func.timestampadd('MINUTES', element.clauses, func.now())
    )

@compiles(durationnow, 'postgresql')
def pg_durationnow(element, compiler, **kw):
    return compiler.process(
        func.now() + func.make_interval(0, 0, 0, 0, 0, element.clauses)
    )

    # Or alternatively...
    # return "now() - make_interval(0, 0, 0, 0, 0, {})".format(compiler.process(element.clauses))
    # which is more in-line with how the documentation uses 'compiles'

通过类似的设置,您应该能够将原始查询转换为直接向SQL呈现的交叉查询,而不是在Python中进行持续时间计算:

With something like that set up you should be able to turn your original query into a cross-dialect one that renders to SQL directly instead of doing the duration computation in Python:

current_appointment = Appointment.query.filter(
    Appointment.datetime.between(
        func.now(),
        durationnow(Appointment.duration)
    ).limit(1).one_or_none()