2010-12-05 12 views
6

¿Hay alguna forma de obtener los registros previos/siguientes de una consulta SqlAlchemy? De este modo:SqlAlchemy prev/next accesors?

record.id 
record.next.id 
record.prev.id 

podría añadir los siguientes métodos/PREV para cada modelo, pero me estoy preguntando si ya hay alguna manera automágicas que pasé por alto. La aplicación web en cuestión está escrita en Pilones.

Editar: Esto es probablemente un truco sucio, pero funciona. Me importa el objeto Session sqlalchemy en mi modelo y lo hizo:

def next(self): 
    return Session.query(Blog).filter(Blog.id > self.id).order_by(Blog.id).first() 

def prev(self): 
    return Session.query(Blog).filter(Blog.id < self.id).order_by(desc(Blog.id)).first() 
+0

Sin cambiar el modelo (al agregar realmente la relación a las tablas), su solución es bastante buena. Lo único que cambiaría es 'Session.query (...' a 'Session.object_session (self) .query (...' (ver http://www.sqlalchemy.org/docs/orm/session). html # sqlalchemy.orm.session.Session.object_session) – van

+0

Para ser claros, Session.query está utilizando la clase de sesión global que se define en su propio proyecto y Session.object_session está utilizando la clase de sesión que viene con sqlalchemy. –

Respuesta

-2

Lo que sugeriría hacer es en su búsqueda original solicitando -1 y +1 de manera que usted puede conseguir fácilmente los ID sin tener que ejecutar otra consulta ahorrando tiempo en el procesamiento en el servidor SQL.

Su solución definitivamente funciona, pero requiere dos consultas adicionales. Incluso podría hacer que sea una subconsulta, de modo que si solo desea recuperar una sola fila y arrojar el anterior/siguiente en ella, esos datos se almacenan en una columna creada por una subconsulta.

+0

min one y plus one no funcionarán si elimina algunos registros mientras tanto. Porque mysql (base de datos) tendrá su propia identificación y no más uno o menos uno. Parece que ahora hay un camino hacia eso. – pregmatch

0

Más 1 y menos 1 en el último registro de la base de datos funcionará a veces. ¿Qué sucede si elimina un par de los últimos registros? La siguiente identificación no será más uno o menos uno en la última identificación. Eso no es cosa de sesión, es algo misterioso. Para obtener la próxima identificación, tendrá que hacer algunas consultas en un esquema de información como este.

q = "SELECT auto_increment FROM INFORMATION_SCHEMA.TABLES WHERE table_name='table_name'" 
a = s.execute(q) #where s is sqlalchemy session 

for b in a: 

    print b 
    print b[0] 

que le dará algo como: (163459L,) 163459

En mi caso que es cierto.

Y para la prev siempre se puede hacer .First() en su último disco. Ese es el registro previo.

0

Esto es lo que uso para recuperar next/prev de un objeto usando sqlalchemy. La idea es conseguir que el row_number del objeto de la lista inicial y hacer una nueva solicitud con un desplazamiento +/- 1.

estoy usando una sub consulta con ROW_NUMBER (How do I use ROW_NUMBER()?) para recuperar el row_number de la consulta inicial:

row_number = func.row_number().over(order_by=orders).label("row_number") 
row_number_subquery = self.getlistquery(columns=chain([row_number], pk_columns)).subquery() 

Entonces me uno con el modelo de las claves primarias:

join_clause = [getattr(row_number_query.c, pk.key) == getattr(model, pk.key) for pk in pk_columns] 

I filtrar por las claves principales del objeto:

filter = [getattr(model, pk.key) == pk_values[index] for index, pk in enumerate(pk_columns)] 

puedo crear la consulta final para conseguir el desplazamiento del objeto:

offset = db.session.query(row_number_subquery).join(model, *join_clause).filter(*filter).first() 

A continuación, el elemento contiene el offset para alcanzar el siguiente o offset-2 para la anterior (como a partir de 1 de row_number y 0 para offset)

self.getlistquery().offset(offset)