PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Python postgreSQL sqlalchemy consulta uma coluna DATERANGE


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

pode ser implementado usando o operador "intervalo contido por" <@ . Para passar o operando correto, você precisa criar uma instância de psycopg2.extras.DateRange , que representa um daterange do Postgresql valor em 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()

Observe que os atributos lower e upper fazem parte do psycopg2.extras.Range tipos. Os tipos de coluna de intervalo SQLAlchemy não fornecem isso, conforme seu erro indica.

Se você quiser usar SQL bruto e passar intervalos de datas, você pode usar o mesmo DateRange objetos para passar valores também:
bookings = db_session.execute(
    'SELECT * FROM usersbookrooms WHERE booked_date && %s',
    (DateRange(the_daterange_lower, the_daterange_upper),))

Você também pode criar literais manualmente , se você quiser:
bookings = db_session.execute(
    'SELECT * FROM usersbookrooms WHERE booked_date && %s::daterange',
    (f'[{the_daterange_lower}, {the_daterange_upper})',))

O truque é construir o literal em Python e passá-lo como um valor único – usando espaços reservados, como sempre. Deve evitar qualquer possibilidade de injeção de SQL; a única coisa que pode acontecer é que o literal tenha uma sintaxe inválida para um daterange . Como alternativa, você pode passar os limites para um construtor de intervalo :
bookings = db_session.execute(
    'SELECT * FROM usersbookrooms WHERE booked_date && daterange(%s, %s)',
    (the_daterange_lower, the_daterange_upper))

Em suma, é mais fácil usar o Psycopg2 Range tipos e deixá-los lidar com os detalhes.