Flask-SQLalchemy aktualisiert die Informationen einer Zeile


Antworten:


205

Rufen Sie ein Objekt mithilfe des in der Flask-SQLAlchemy-Dokumentation gezeigten Lernprogramms ab . Sobald Sie die Entität haben, die Sie ändern möchten, ändern Sie die Entität selbst. Dann db.session.commit().

Beispielsweise:

admin = User.query.filter_by(username='admin').first()
admin.email = 'my_new_email@example.com'
db.session.commit()

user = User.query.get(5)
user.name = 'New Name'
db.session.commit()

Flask-SQLAlchemy basiert auf SQLAlchemy. Lesen Sie daher auch die SQLAlchemy-Dokumente .


2
Danke Mark. Eine andere Sache. Ich habe gesehen, wie es so gemacht wurde: 'db.add (Benutzer)', dann 'dv.session.commit ()'. Warum funktionieren beide? und was ist der Unterschied?
Pocorschi

11
Dies hat mit den Unterschieden zwischen vorübergehenden, getrennten und angehängten Objekten in SQLAlchemy zu tun (siehe sqlalchemy.org/docs/orm/session.html#what-does-the-session-do ). Lesen Sie auch den Kommentar von Michael Bayer auf der Mailingliste ( groups.google.com/group/sqlalchemy/browse_thread/thread/… ), um weitere Informationen zu erhalten.
Mark Hildreth

1
Wenn Sie nach dem Lesen immer noch verwirrt sind, sollten Sie eine andere Frage stellen.
Mark Hildreth

Wenn der Spaltendatentyp json ist, verwenden Sie die folgende Methode. bashelton.com/2014/03/…
Aram

@MarkHildreth Ich konnte keinen Datum / Uhrzeit-Wert für das Feld aktualisieren. Was soll ich tun? Spalte ist uesd_at = db.Column(db.DateTime)ich nur ausführen, obj.used_at = datetime.datetime.now() db.session.commit()aber kein Wert auf das Feld gesetzt.
Rukeith

96

updateIn SQLAlchemy gibt es eine Methode für das BaseQuery-Objekt, die von zurückgegeben wird filter_by.

admin = User.query.filter_by(username='admin').update(dict(email='my_new_email@example.com')))
db.session.commit()

Der Vorteil der Verwendung updategegenüber dem Ändern der Entität ergibt sich, wenn viele Objekte aktualisiert werden müssen.

Wenn Sie add_userallen admins die Erlaubnis geben möchten ,

rows_changed = User.query.filter_by(role='admin').update(dict(permission='add_user'))
db.session.commit()

Beachten Sie, dass filter_bySchlüsselwortargumente verwendet werden (verwenden Sie nur eines =), während filterein Ausdruck verwendet wird.


1
In der ersten Abfrage wird das Ergebnis als benannt admin, was irreführend sein kann, da das Ergebnis die Anzahl der aktualisierten Zeilen ist. Ist es nicht?
Vikas Prasad

und gibt es eine Möglichkeit, wie ich die betroffenen UserElemente von der Abfrage abrufen kann, nicht die Anzahl der betroffenen Benutzer?
Vikas Prasad

Anzahl der übereinstimmenden
Vikas Prasad

18

Dies funktioniert nicht, wenn Sie ein ausgewähltes Attribut des Modells ändern. Eingelegte Attribute sollten ersetzt werden, um Aktualisierungen auszulösen:

from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from pprint import pprint

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqllite:////tmp/users.db'
db = SQLAlchemy(app)


class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(80), unique=True)
    data = db.Column(db.PickleType())

    def __init__(self, name, data):
        self.name = name
        self.data = data

    def __repr__(self):
        return '<User %r>' % self.username

db.create_all()

# Create a user.
bob = User('Bob', {})
db.session.add(bob)
db.session.commit()

# Retrieve the row by its name.
bob = User.query.filter_by(name='Bob').first()
pprint(bob.data)  # {}

# Modifying data is ignored.
bob.data['foo'] = 123
db.session.commit()
bob = User.query.filter_by(name='Bob').first()
pprint(bob.data)  # {}

# Replacing data is respected.
bob.data = {'bar': 321}
db.session.commit()
bob = User.query.filter_by(name='Bob').first()
pprint(bob.data)  # {'bar': 321}

# Modifying data is ignored.
bob.data['moo'] = 789
db.session.commit()
bob = User.query.filter_by(name='Bob').first()
pprint(bob.data)  # {'bar': 321}

1
Was ist in solchen Fällen der beste Ansatz?
Kampta

Sie müssten es kopieren dataund neu zuweisen.
Sas

@sas Was meinst du?
Mote Zart

Sie müssen die Dateneigenschaft kopieren und zuweisen, um den Aktualisierungsmechanismus auszulösen. Schauen Sie sich die Antwort unten an:user.data = data
sas

9

Das Zuweisen und Festschreiben des Werts funktioniert für alle Datentypen außer den Attributen JSON und Pickled. Da der eingelegte Typ oben erläutert wurde, werde ich eine etwas andere, aber einfache Möglichkeit zum Aktualisieren von JSONs aufzeigen.

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(80), unique=True)
    data = db.Column(db.JSON)

def __init__(self, name, data):
    self.name = name
    self.data = data

Angenommen, das Modell ist wie oben.

user = User("Jon Dove", {"country":"Sri Lanka"})
db.session.add(user)
db.session.flush()
db.session.commit()

Dadurch wird der Benutzer mit den Daten {"Land": "Sri Lanka"} zur MySQL-Datenbank hinzugefügt.

Das Ändern von Daten wird ignoriert. Mein Code, der nicht funktioniert hat, lautet wie folgt.

user = User.query().filter(User.name=='Jon Dove')
data = user.data
data["province"] = "south"
user.data = data
db.session.merge(user)
db.session.flush()
db.session.commit()

Anstatt die schmerzhafte Arbeit des Kopierens des JSON in ein neues Diktat (ohne es wie oben einer neuen Variablen zuzuweisen) zu durchlaufen, die hätte funktionieren sollen, fand ich einen einfachen Weg, dies zu tun. Es gibt eine Möglichkeit, das von JSONs geänderte System zu kennzeichnen.

Es folgt der Arbeitscode.

from sqlalchemy.orm.attributes import flag_modified
user = User.query().filter(User.name=='Jon Dove')
data = user.data
data["province"] = "south"
user.data = data
flag_modified(user, "data")
db.session.merge(user)
db.session.flush()
db.session.commit()

Das hat wie ein Zauber gewirkt. Zusammen mit dieser Methode wird hier eine andere Methode vorgeschlagen. Ich hoffe, ich habe jemandem geholfen.


2
db.session.merge(user)Das Hinzufügen dieses Codes hat bei mir funktioniert, FYI.
Jeff Bluemel
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.