PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Python postgreSQL sqlalchemy interroge une colonne DATERANGE

La requête

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

pourrait être implémenté en utilisant l'opérateur "la plage est contenue par" <@ . Afin de passer le bon opérande, vous devez créer une instance de psycopg2.extras.DateRange , qui représente un daterange Postgresql valeur 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()

Notez que les attributs lower et upper font partie de la psycopg2.extras.Range les types. Les types de colonne de plage SQLAlchemy ne fournissent pas de tels, comme l'indique votre erreur.

Si vous souhaitez utiliser du SQL brut et transmettre des plages de dates, vous pouvez utiliser le même DateRange objets pour transmettre également des valeurs :

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

Vous pouvez également créer des littéraux manuellement , si vous souhaitez :

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

L'astuce consiste à construire le littéral en Python et à le transmettre en tant que valeur unique - en utilisant des espaces réservés, comme toujours. Il doit éviter toute possibilité d'injection SQL ; la seule chose qui peut arriver est que le littéral a une syntaxe invalide pour un daterange . Vous pouvez également passer les limites à un constructeur de plage :

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

Dans l'ensemble, il est plus facile d'utiliser simplement la Range Psycopg2 types et laissez-les gérer les détails.