L'application de limite et de OFFSET à toutes les requêtes en SQLAlchemy
je suis en train de concevoir une API avec SQLAlchemy (interrogation MySQL) et j'aimerais forcer toutes mes requêtes à avoir les paramètres page_size (LIMIT) et page_number (OFFSET).
y a-t-il une façon propre de faire cela avec SQLAlchemy? Peut-être construire une usine d'une sorte pour créer un objet de requête personnalisé? Ou peut-être qu'il y a un bon moyen de faire ça avec un cours de mixin?
j'ai essayé la chose évidente et ça n'a pas fonctionné parce que .limit() et .offset () doit être appelé après tous les filtres les conditions ont été appliquées:
def q(page=0, page_size=None):
q = session.query(...)
if page_size: q = q.limit(page_size)
if page: q = q.offset(page*page_size)
return q
Quand j'ai essayer d'utiliser ceci, j'obtiens l'exception:
sqlalchemy.exc.InvalidRequestError: Query.filter() being called on a Query which already has LIMIT or OFFSET applied. To modify the row-limited results of a Query, call from_self() first. Otherwise, call filter() before limit() or offset() are applied.
2 réponses
essayez d'ajouter un premier argument requis, qui doit être un groupe de filtres de requête. Ainsi,
# q({'id': 5}, 2, 50)
def q(filters, page=0, page_size=None):
query = session.query(...).filter_by(**filters)
if page_size:
query = query.limit(page_size)
if page:
query = query.offset(page*page_size)
return query
ou
# q(Model.id == 5, 2, 50)
def q(filter, page=0, page_size=None):
query = session.query(...).filter(filter)
if page_size:
query = query.limit(page_size)
if page:
query = query.offset(page*page_size)
return query
ce n'est Pas une option au moment de cette question, depuis la version 1.0.0, vous pouvez profiter de l' Requête événements pour vous assurer limit
et offset
les méthodes sont toujours appelé juste avant votre query
objet est compilé, après toute manipulation est effectuée par les utilisateurs de votre q
fonction:
from sqlalchemy.event import listen
def q(page=0, page_size=None):
query = session.query()
listen(query, 'before_compile', apply_limit(page, page_size), retval=True)
return query
def apply_limit(page, page_size):
def wrapped(query):
if page_size:
query = query.limit(page_size)
if page:
query = query.offset(page * page_size)
return query
return wrapped