web-dev-qa-db-fra.com

Flask-SQLalchemy met à jour les informations d'une ligne

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.

90
pocorschi

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 .

171
Mark Hildreth

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 admins,

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.

78
Devi

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}
15
Bevan

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.