PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Python postgreSQL sqlalchemy interroga una colonna DATERANGE

La domanda

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

potrebbe essere implementato utilizzando l'operatore "l'intervallo è contenuto da" <@ . Per passare l'operando corretto devi creare un'istanza di psycopg2.extras.DateRange , che rappresenta un daterange Postgresql valore in 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()

Nota che gli attributi lower e upper fanno parte di psycopg2.extras.Range tipi. I tipi di colonna dell'intervallo SQLAlchemy non forniscono tali, come indica il tuo errore.

Se desideri utilizzare SQL non elaborato e passare intervalli di date, puoi utilizzare lo stesso DateRange anche gli oggetti per passare valori:

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

Puoi anche creare letterali manualmente , se vuoi:

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

Il trucco è costruire il letterale in Python e passarlo come valore singolo, usando i segnaposto, come sempre. Dovrebbe evitare qualsiasi possibilità di iniezione SQL; l'unica cosa che può succedere è che il valore letterale abbia una sintassi non valida per un daterange . In alternativa puoi passare i limiti a un costruttore di intervalli :

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

Tutto sommato è più facile usare semplicemente il Range di Psycopg2 tipi e lasciare che gestiscano i dettagli.