Odpowiedzi:
Pobierz obiekt, korzystając z samouczka przedstawionego w dokumentacji Flask-SQLAlchemy . Gdy masz już encję, którą chcesz zmienić, zmień samą jednostkę. Następnie db.session.commit()
.
Na przykład:
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 jest oparty na SQLAlchemy, więc koniecznie zapoznaj się również z dokumentami SQLAlchemy .
uesd_at = db.Column(db.DateTime)
po prostu uruchomiona, obj.used_at = datetime.datetime.now()
db.session.commit()
ale nie wartość ustawiona na pole.
W update
obiekcie BaseQuery w SQLAlchemy istnieje metoda , która jest zwracana przez filter_by
.
admin = User.query.filter_by(username='admin').update(dict(email='my_new_email@example.com')))
db.session.commit()
Zaletą używania update
nad zmianą jednostki jest sytuacja, gdy istnieje wiele obiektów do zaktualizowania.
Jeśli chcesz add_user
zezwolić wszystkim admin
,
rows_changed = User.query.filter_by(role='admin').update(dict(permission='add_user'))
db.session.commit()
Zauważ, że filter_by
przyjmuje argumenty słów kluczowych (użyj tylko jednego =
), w przeciwieństwie do tego, filter
który przyjmuje wyrażenie.
admin
, co może być mylące, ponieważ wynikiem będzie liczba zaktualizowanych wierszy. Prawda?
User
elementy, których dotyczy zapytanie, a nie liczbę użytkowników, których dotyczy zapytanie?
To nie zadziała, jeśli zmodyfikujesz marynowany atrybut modelu. Marynowane atrybuty należy wymienić, aby wywołać aktualizacje:
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}
data
i przypisać.
user.data = data
Samo przypisanie wartości i zatwierdzenie ich zadziała dla wszystkich typów danych oprócz atrybutów JSON i Pickled. Ponieważ typ marynowany jest wyjaśniony powyżej, zanotuję nieco inny, ale łatwy sposób aktualizacji JSON.
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
Powiedzmy, że model jest taki jak powyżej.
user = User("Jon Dove", {"country":"Sri Lanka"})
db.session.add(user)
db.session.flush()
db.session.commit()
Spowoduje to dodanie użytkownika do bazy danych MySQL z danymi {"country": "Sri Lanka"}
Modyfikowanie danych zostanie zignorowane. Mój kod, który nie zadziałał, jest następujący.
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()
Zamiast przechodzić przez bolesną pracę polegającą na kopiowaniu JSON do nowego dyktu (nie przypisując go do nowej zmiennej jak wyżej), co powinno zadziałać, znalazłem prosty sposób na zrobienie tego. Istnieje sposób na oznaczenie systemu, że zmieniły się JSON.
Poniżej znajduje się działający kod.
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()
To zadziałało jak urok. Jest jeszcze inna metoda zaproponowana wraz z tej metody tutaj nadzieję, że pomogliśmy kogoś.
db.session.merge(user)
dodanie tego kodu zadziałało dla mnie, FYI.