2012-11-06 9 views
25

Ich entwerfe eine API mit SQLAlchemy (Abfrage von MySQL) und ich möchte alle meine Abfragen zwingen, page_size (LIMIT) und page_number (OFFSET) Parameter zu haben.Anwenden von LIMIT und OFFSET auf alle Abfragen in SQLAlchemy

Gibt es einen sauberen Weg, dies mit SQLAlchemy zu tun? Vielleicht eine Art Factory erstellen, um ein benutzerdefiniertes Query-Objekt zu erstellen? Oder vielleicht gibt es eine gute Möglichkeit, dies mit einer Mixing-Klasse zu tun?

habe ich versucht, die offensichtliche Sache, und es hat nicht funktioniert, weil .limit() und .Offset() aufgerufen werden muss, nachdem alle Filterbedingungen angewandt wurden:

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 

Wenn ich das versuchen Sie es mit, ich Erhalten Sie die Ausnahme:

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. 
+0

Bitte keine Änderungen vornehmen, eine Lösung in Frage. Stattdessen posten Sie es als separate Antwort unten. – Matt

Antwort

25

Versuchen Sie, ein erstes erforderliches Argument hinzuzufügen, das eine Gruppe von Abfragefiltern sein muss. So

# 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 

oder

# 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 
+1

Indem wir es in zwei Teile aufteilen (Abfrageobjekt abfragen, obligatorische Filter anwenden), verlassen wir uns darauf, dass der Entwickler daran denkt, q() für alle seine Abfragen aufzurufen. Ergebnisse werden immer noch generiert, wenn jemand vergisst, q() vor dem Aufruf von all() aufzurufen. –

+0

Dann müssen Sie statt einer Abfrage ein Filterwörterbuch nehmen. Aber das wird dich etwas einschränken. – pydsigner

+1

@RobCrowell Drei Jahre später bin ich neugierig, ob das dein Problem gelöst hat oder ob du etwas anderes gemacht hast (in diesem Fall wäre es schön zu sehen, dass du eine Antwort über das, was du herausgefunden hast, einreichst)? – pydsigner