Comment puis-je mettre à jour les informations d'une ligne?
Par exemple, je voudrais modifier la colonne de nom de la ligne qui a l'identifiant 5.
Récupérez un objet à l'aide de tutoriel présenté dans la documentation de Flask-SQLAlchemy . Une fois que vous avez l'entité que vous voulez changer, changez l'entité elle-même. Ensuite, db.session.commit()
.
Par exemple:
admin = User.query.filter_by(username='admin').first()
admin.email = '[email protected]'
db.session.commit()
user = User.query.get(5)
user.name = 'New Name'
db.session.commit()
Flask-SQLAlchemy est basé sur SQLAlchemy, assurez-vous donc de vérifier les SQLAlchemy Docs .
Il existe une méthode update
sur un objet BaseQuery dans SQLAlchemy, qui est renvoyée par filter_by
.
admin = User.query.filter_by(username='admin').update(dict(email='[email protected]')))
db.session.commit()
L'avantage d'utiliser update
par rapport à la modification de l'entité vient lorsque de nombreux objets doivent être mis à jour.
Si vous voulez donner add_user
permission à tous les admin
s,
rows_changed = User.query.filter_by(role='admin').update(dict(permission='add_user'))
db.session.commit()
Remarquerez que filter_by
prend les arguments de mots clés (utilisez un seul =
) par opposition à filter
qui prend une expression.
Cela ne fonctionne pas si vous modifiez un attribut décapé du modèle. Les attributs picklés doivent être remplacés afin de déclencher des mises à jour:
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}
Le simple fait d'attribuer la valeur et de les valider fonctionnera pour tous les types de données, à l'exception des attributs JSON et Pickled. Comme le type de saumure est expliqué ci-dessus, je vais noter un moyen légèrement différent mais facile de mettre à jour les 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
Disons que le modèle est comme ci-dessus.
user = User("Jon Dove", {"country":"Sri Lanka"})
db.session.add(user)
db.session.flush()
db.session.commit()
Ceci ajoutera l'utilisateur à la base de données MySQL avec les données {"pays": "Sri Lanka"}
La modification des données sera ignorée. Mon code qui n'a pas fonctionné est le suivant.
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()
Au lieu de passer par le travail pénible de copier le JSON dans un nouveau dict (et non de l'attribuer à une nouvelle variable comme ci-dessus), ce qui aurait dû fonctionner a permis de trouver un moyen simple de le faire. Il existe un moyen de signaler au système que les JSON ont été modifiés.
Voici le code de travail.
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()
Cela a fonctionné comme un charme. Il existe une autre méthode proposée avec cette méthode ici J'espère avoir aidé quelqu'un.