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.
28
demandé sur Matt 2012-11-07 00:34:03

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
29
répondu pydsigner 2016-02-23 19:00:25

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
0
répondu Daniele 2018-06-22 10:21:23