sql >> Base de Datos >  >> RDS >> PostgreSQL

Python postgreSQL sqlalchemy consulta una columna DATERANGE

La consulta

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()

podría implementarse usando el operador "el rango está contenido en" <@ . Para pasar el operando correcto, debe crear una instancia de psycopg2.extras.DateRange , que representa un daterange de Postgresql valor en Python:

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()

Tenga en cuenta que los atributos lower y upper son parte del psycopg2.extras.Range tipos Los tipos de columnas de rango de SQLAlchemy no proporcionan tales, como indica su error.

Si desea usar SQL sin procesar y pasar rangos de fechas, puede usar el mismo DateRange objetos para pasar valores también:

bookings = db_session.execute(
    'SELECT * FROM usersbookrooms WHERE booked_date && %s',
    (DateRange(the_daterange_lower, the_daterange_upper),))

También puede construir literales manualmente , si quieres:

bookings = db_session.execute(
    'SELECT * FROM usersbookrooms WHERE booked_date && %s::daterange',
    (f'[{the_daterange_lower}, {the_daterange_upper})',))

El truco es construir el literal en Python y pasarlo como un valor único, usando marcadores de posición, como siempre. Debería evitar cualquier posibilidad de inyección SQL; lo único que puede suceder es que el literal tenga una sintaxis no válida para un daterange . Alternativamente, puede pasar los límites a un constructor de rango :

bookings = db_session.execute(
    'SELECT * FROM usersbookrooms WHERE booked_date && daterange(%s, %s)',
    (the_daterange_lower, the_daterange_upper))

En general, es más fácil usar el Range de Psycopg2 tipos y déjelos manejar los detalles.