2010-05-13 3 views
7

Ich habe SQLAlchemy auf 0,6 aktualisiert, aber es brach alles. Ich habe bemerkt, dass es kein Wörterbuch mehr gibt. Hier ist eine Beispielabfrage:SQLAlchemy gibt Tupel nicht Wörterbuch

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

Dieses Stück Code verwendet, um ein Wörterbuch in 0.5 zurückzugeben.

Meine Frage ist, wie kann ich ein Wörterbuch zurückgeben?

+2

Einfach nur neugierig: Warum gehst du nicht tun 'session.query (Benutzer) .get (id)' (User.id unter der Annahme ist der Primärschlüssel) . Oder 'session.query (Benutzer) .filter (User.id == id) .filter (User.username == Benutzername) .first()' wenn ID kein Primärschlüssel ist. Tun Sie das und Sie erhalten eine Benutzerinstanz zurück, und Sie können auf die Feldwerte durch Attributsuche zugreifen. – codeape

Antwort

5

Dies sollte funktionieren: dict(zip(['id','username','email'],result)) (oder Sie könnten ein Wörterbuch Verständnis verwenden, wenn Sie auf Python 3.x sind).
Sie müssen auch nicht session.execute auf einem session.query Objekt aufrufen. Sie sollten stattdessen die Methode .one() verwenden. Dies macht es auch überflüssig, dass der .limit(1)-Aufruf am Ende Ihrer Anfrage hängt.

+0

Ja, es funktioniert. Vielen Dank. Ich benutze limit (1), denn wenn ich mir die SQL-Anweisung anschaue, die SQLALchemy für diesen Code erstellt, enthält sie LIMIT 1 nicht in der Abfrage. – Ivan

8

Sind Sie sicher, dass es kein ResultProxy ist, der vorgibt, ein Tupel zu sein, wenn Sie es drucken? Viele Objekte im ORM sind nicht das, was ihre __str__-Funktion zurückgibt.

+0

+1 Ich wurde völlig von dem, was ich sah, bis ich das las gelesen. Nachdem ich gelesen hatte, ging ich einfach weiter und versuchte es mit den Feldnamen und es funktionierte perfekt! Er hat mir viele Kopfschmerzen erspart. Vielen Dank. –

33

session.execute hat noch nie ein dict zurückgekehrt, es gibt ein RowProxy Objekt, das wie ein dict entweder ganzzahlige Schlüssel für Positions Lookup indiziert werden können, String-Schlüssel für Label aus Lookup oder Column-Objekte den Wert zum Nachschlagen dieser Spalte. Das Problem hier ist, dass nicht das tut, was Sie zu erwarten scheinen. Es konvertiert das Query-Objekt in eine Select-Anweisung, führt dies aus und gibt das Ergebnis direkt zurück. Das Resultset weiß nichts über ORM-Level-Features. Was zwischen 0.5 und 0.6 geändert wurde, ist, dass ORM einen anderen Algorithmus verwendet, um die Spalten in Abfragen zu beschriften, es fügt nun den Tabellennamen dem Label voran. Also, wenn vorher row['id'] passiert ist, funktioniert jetzt row['users_id'] funktioniert. In beiden Fällen funktioniert row[User.__table__.columns['id']].

Um ORM-Abfragen auszuführen, sollten Sie tatsächlich die Methoden .all(), .first() und .one() verwenden oder darüber iterieren oder numerische Indexierung verwenden. Abfrage gibt benannte Tupel-Objekte zurück. Zip das Tupel mit seinen Tasten, wenn Sie einen dict wollen:

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