2012-11-06 13 views
25

Projektuję interfejs API z SQLAlchemy (wysyłanie zapytań do MySQL) i chciałbym wymusić na wszystkich moich zapytaniach parametry page_size (LIMIT) i page_number (OFFSET).Stosowanie LIMIT i OFFSET do wszystkich zapytań w SQLAlchemy

Czy istnieje czysty sposób robienia tego z SQLAlchemy? Być może budowanie fabryki jakiegoś rodzaju, aby utworzyć niestandardowy obiekt zapytania? A może jest dobry sposób na zrobienie tego z klasą mixin?

Próbowałem oczywistą rzeczą i to nie działa, ponieważ .limit() i .offset() musi być wywołana po wszystkie warunki zostały zastosowane filtry:

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 

gdy próbuję za pomocą tego, ja z wyjątkiem:

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

Proszę nie edytować roztwór do Twojego pytania. Zamiast tego zamieść go jako osobną odpowiedź poniżej. – Matt

Odpowiedz

25

Spróbuj dodać pierwszy, wymagany argument, który musi być grupą filtrów zapytań. Zatem

# 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 

lub

# 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

Poprzez podzielenie go na 2 części (pobierz obiekt zapytania, zastosuj obowiązkowe filtry), polegamy na programistach, aby pamiętać o wywołaniu q() we wszystkich jego zapytaniach. Wyniki będą nadal generowane, jeśli ktoś zapomni zadzwonić q() przed wywołaniem all(). –

+0

Następnie należy pobrać słownik kwerendy zamiast kwerendy. Ale to cię trochę ograniczy. – pydsigner

+1

@RobCrowell Trzy lata później, jestem ciekawy, czy to rozwiązało twój problem, czy też skończyło się na zrobieniu czegoś innego (w takim przypadku byłoby miło zobaczyć, że przesłałeś odpowiedź na temat tego, co wymyśliłeś)? – pydsigner

Powiązane problemy