Zeile (SQLAlchemy) mit Daten aus Marshmallow aktualisieren

9

Ich verwende Flask, Flask-SQLAlchemy, Flask-Marshmallow + Marshmallow-sqlalchemy und versuche, die REST-API-PUT-Methode zu implementieren. Ich habe kein Tutorial gefunden, das SQLA und Marshmallow verwendet, die das Update implementieren.

Hier ist der Code:

%Vor%     
gcerar 08.08.2015, 09:31
quelle

3 Antworten

15

Sie müssen das zu bearbeitende Objekt in schema.load () wie folgt übergeben:

%Vor%

Und wenn Sie ohne alle erforderlichen Felder von Model laden möchten, können Sie das "partially = True" wie folgt hinzufügen:

%Vor%

Ссылка

    
Jair Perrut 05.04.2016, 07:04
quelle
2

Ich habe eine eigene Lösung ausgerollt. Hoffe es hilft jemand anderem. Lösung implementiert Update-Methode für das Knotenmodell.

Lösung:

%Vor%     
gcerar 08.08.2015 18:49
quelle
0

Ich habe einige Zeit mit diesem Thema gerungen und bin deshalb immer wieder auf diesen Posten zurückgekommen. Was am Ende meine Situation erschwerte, war, dass es ein Problem mit SQLAlchemy-Sitzungen gab. Ich denke, das ist für Flask, Flask-SQLAlchemy, SQLAlchemy und Marshmallow genug, um eine Diskussion niederzuschlagen. Ich behaupte natürlich nicht, ein Experte darin zu sein, und dennoch glaube ich, dass das, was ich unten darstelle, im Wesentlichen korrekt ist.

Die db.session ist in der Tat eng mit dem Prozess der Aktualisierung der DB mit Marshmallow verbunden, und aus diesem Grund entschieden, um die Details zu geben, aber zuerst kurz.

Kurze Antwort

Hier ist die Antwort, die ich zum Aktualisieren der Datenbank mit Marshmallow erhalten habe. Es ist ein anderer Ansatz als der sehr hilfreiche Beitrag von Jair Perrut. Ich habe mir die Marshmallow-API angeschaut und war dennoch nicht in der Lage, seine Lösung in dem präsentierten Code zu verwenden, da ich zu der Zeit, als ich mit seiner Lösung experimentierte, meine SQLAlchemy-Sitzungen nicht richtig verwaltete. Um etwas weiter zu gehen, könnte man sagen, dass ich sie überhaupt nicht leitete. Das Modell kann auf folgende Weise aktualisiert werden:

%Vor%

Geben Sie session.add () ein Modell mit Primärschlüssel und es wird eine Aktualisierung angenommen. Lassen Sie den Primärschlüssel aus und erstellen Sie stattdessen einen neuen Datensatz. Dies ist nicht allzu überraschend, da MySQL eine ON DUPLICATE KEY UPDATE -Klausel hat, die eine Aktualisierung durchführt, wenn der Schlüssel vorhanden ist, und wenn nicht, erstellt.

Details

SQLAlchemy-Sitzungen werden von Flask-SQLAlchemy während einer Anforderung an die Anwendung behandelt. Zu Beginn der Anfrage wird die Sitzung geöffnet, und wenn die Anfrage geschlossen wird, wird diese Sitzung ebenfalls geschlossen. Flask bietet Hooks zum Einrichten und Herunterfahren der Anwendung, wo Code zum Verwalten von Sitzungen und Verbindungen gefunden werden kann. Am Ende wird die SQLAlchemy-Sitzung vom Entwickler verwaltet und Flask-SQLAlchemy hilft nur. Hier ist ein spezieller Fall, der die Verwaltung von Sitzungen veranschaulicht.

Stellen Sie sich eine Funktion vor, die ein Benutzerwörterbuch als Argument erhält und dieses mit Marshmallow () verwendet, um das Wörterbuch in ein Modell zu laden. In diesem Fall ist nicht die Erstellung eines neuen Objekts erforderlich, sondern die Aktualisierung eines vorhandenen Objekts. Es gibt zwei Dinge, die man am Anfang beachten sollte:

  • Die Modellklassen werden in einem Python-Modul getrennt von jedem Code definiert, und diese Modelle erfordern die Sitzung. Oft wird der Entwickler (Flask-Dokumentation) eine Zeile db = SQLAlchemy() an den Anfang dieser Datei setzen, um diese Anforderung zu erfüllen. Dies erstellt tatsächlich eine Sitzung für das Modell.
    • from flask_sqlalchemy import SQLAlchemy
    • db = SQLAlchemy()
  • In einigen anderen separaten Dateien kann auch eine SQLAlchemy-Sitzung erforderlich sein. Beispielsweise muss der Code das Modell möglicherweise aktualisieren oder einen neuen Eintrag erstellen, indem eine Funktion dort aufgerufen wird. Hier finden Sie db.session.add(user_model) und db.session.commit(). Diese Sitzung wird auf die gleiche Weise wie im obigen Aufzählungspunkt erstellt.

Es sind 2 SQLAlchemy-Sitzungen erstellt. Das Modell befindet sich in einer (SignallingSession) und das Modul verwendet eine eigene (scoped_session). Tatsächlich gibt es 3. Der Marshmallow UserSchema hat sqla_session = db.session : eine Sitzung ist daran angehängt. Dies ist dann der dritte und die Details finden Sie im folgenden Code:

%Vor%

An der Spitze dieses Moduls wird das Modell importiert, das seine Sitzung erstellt, und dann erstellt das Modul sein eigenes. Wie bereits erwähnt, gibt es natürlich auch die Marshmallow-Session. Dies ist bis zu einem gewissen Grad akzeptabel, da SQLAlchemy es dem Entwickler ermöglicht, die Sitzungen zu verwalten. Berücksichtigen Sie, was passiert, wenn some_function(user) aufgerufen wird, wobei user['id'] einen Wert zugewiesen bekommt, der in der Datenbank vorhanden ist.

Da user einen gültigen Primärschlüssel enthält, weiß db.session.add(user_model.data) , dass es keine neue Zeile erstellt, sondern eine bestehende aktualisiert. Dieses Verhalten sollte nicht überraschend sein und sollte zumindest etwas erwartet werden, da es aus der MySQL-Dokumentation:

  

13.2.5.2 INSERT ... ON DUPLICATE KEY UPDATE Syntax
  Wenn Sie eine ON DUPLICATE KEY UPDATE-Klausel angeben und eine einzufügende Zeile einen doppelten Wert in einem UNIQUE-Index oder PRIMARY KEY verursacht, wird ein UPDATE der alten Zeile ausgeführt.

Das Code-Snippet aktualisiert dann das customer_id im Wörterbuch für den Benutzer mit dem Primärschlüssel 32155161. Das neue customer_id ist '654321'. Das Wörterbuch wird mit Marshmallow geladen und ein Commit für die Datenbank ausgeführt. Bei der Überprüfung der Datenbank kann festgestellt werden, dass sie tatsächlich aktualisiert wurde. Sie können dies auf zwei Arten versuchen:

  • Im Code: db.session.query(UserModel).filter_by(id=325516).first()
  • In MySQL: select * from user

Wenn Sie Folgendes berücksichtigen sollten:

  • Im Code: UserModel.query.filter_by(id=3255161).customer_id

Sie würden feststellen, dass die Abfrage None zurückbringt. Das Modell ist nicht mit der Datenbank synchronisiert. Ich habe es versäumt, unsere SQLAlchemy-Sitzungen korrekt zu verwalten.Um dies zu verdeutlichen, sollten Sie die Ausgabe der print-Anweisungen bei separaten Importen berücksichtigen:

  • <sqlalchemy.orm.session.SignallingSession object at 0x7f81b9107b90>
  • <sqlalchemy.orm.session.SignallingSession object at 0x7f81b90a6150>
  • <sqlalchemy.orm.scoping.scoped_session object at 0x7f81b95eac50>

In diesem Fall unterscheidet sich die Sitzung UserModel.query von der Marshmallow-Sitzung. Die Marshmallow-Sitzung wird geladen und hinzugefügt. Dies bedeutet, dass beim Abfragen des Modells unsere Änderungen nicht angezeigt werden. In der Tat, wenn wir das tun:

  • db.session.object_session (benutzer_modell.data) .commit ()

Die Modellabfrage bringt nun die aktualisierte customer_id! Betrachten Sie die zweite Alternative, bei der die Importe über flask_essentials erfolgen:

%Vor%
  • <sqlalchemy.orm.session.SignallingSession object at 0x7f00fe227910>
  • <sqlalchemy.orm.session.SignallingSession object at 0x7f00fe227910>
  • <sqlalchemy.orm.scoping.scoped_session object at 0x7f00fed38710>

Und die Sitzung UserModel.query ist jetzt die gleiche wie die Sitzung user_model.data (Marshmallow). Die UserModel.query spiegelt nun die Änderung in der Datenbank wider: die Sitzungen Marshmallow und UserModel.query sind identisch.

Hinweis: Die Signalisierungssitzung ist die Standardsitzung, die Flask-SQLAlchemy verwendet. Es erweitert das Standardsitzungssystem um die Auswahl und Verfolgung von Bindungen.

    
Aaron 10.01.2018 19:33
quelle