2010-05-13 13 views
7

He actualizado SQLAlchemy a 0.6 pero rompió todo. Me he dado cuenta de que ya no devuelve tuple un diccionario. Aquí hay una consulta de muestra:SQLAlchemy devuelve tuple no diccionario

query = session.query(User.id, User.username, User.email).filter(and_(User.id == id, User.username == username)).limit(1) 
result = session.execute(query).fetchone() 

Este código utiliza para devolver un diccionario en 0.5.

Mi pregunta es ¿cómo puedo devolver un diccionario?

+2

Sólo por curiosidad: ¿Por qué no haces 'session.query (Usuario) .get (id)' (suponiendo User.id es la clave primaria) . O 'session.query (User) .filter (User.id == id) .filter (User.username == username) .first()' if id no es una clave primaria. Haga eso y obtendrá una instancia de Usuario y podrá acceder a los valores de campo por búsqueda de atributos. – codeape

Respuesta

5

Esto debería funcionar: dict(zip(['id','username','email'],result)) (o podría utilizar la comprensión de un diccionario si está en Python 3.x).
Además, no es necesario que llame al session.execute en un objeto session.query. En su lugar, querrá utilizar el método .one(). Esto también evita la necesidad de que la llamada .limit(1) cuelgue al final de su consulta.

+0

Sí, funciona. Gracias. Utilizo el límite (1) porque cuando miro la declaración SQL que SQLALchemy crea para este código, no incluye el LÍMITE 1 en la consulta. – Ivan

8

¿Está seguro de que no es un ResultProxy que pretende ser una tupla cuando lo imprime? Muchos objetos en el ORM no son lo que devuelve su función __str__.

+0

+1 Estaba totalmente sorprendido por lo que estaba viendo hasta que leí esto. Después de leer, ¡seguí adelante y traté de usar los nombres de campo y funcionó perfectamente! Me salvó un montón de dolor de cabeza. Gracias. –

33

session.execute nunca ha devuelto un dict, devuelve un objeto RowProxy, que puede ser indexado como un dict ya sea utilizando las teclas de números enteros para la búsqueda posicional, claves de cadena para la etiqueta basan búsqueda arriba o columna objetos para buscar el valor de esa columna. El problema aquí es que session.execute(query) no hace lo que parece esperar que haga. Convierte el objeto Query a una instrucción Select, lo ejecuta y devuelve el resultado directamente. El conjunto de resultados no sabe nada sobre las características del nivel de ORM. Lo que cambió entre 0,5 y 0,6 es que ORM usa un algoritmo diferente para etiquetar las columnas en las consultas, ahora lo antepone a la etiqueta. Entonces, cuando anteriormente row['id'] funcionó, ahora funciona row['users_id']. En ambos casos funciona row[User.__table__.columns['id']].

Para ejecutar consultas ORM, debe utilizar los métodos .all(), .first() y .one() o repetirlos o utilizar la indexación numérica. Las consultas devuelven el nombre de objetos de tupla. Zip la tupla con sus llaves si quieres un dict:

row = session.query(User.id, User.username, User.email)\ 
    .filter(and_(User.id == id, User.username == username)).first() 
print("id=%s username=%s email=%s" % row) # positional 
print(row.id, row.username) # by label 
print(dict(zip(row.keys(), row))) # as a dict