Frasco-SQLalchemy actualiza la información de una fila

¿Cómo puedo actualizar la información de una fila?

Por ejemplo, me gustaría alterar la columna de nombre de la fila que tiene el id 5.

Recupere un objeto utilizando el tutorial que se muestra en la documentación de Flask-SQLAlchemy . Una vez que tenga la entidad que desea cambiar, cambie la entidad en sí. Entonces, db.session.commit() .

Por ejemplo:

 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 se basa en SQLAlchemy, así que asegúrate de revisar también los documentos de SQLAlchemy .

Hay una update método en el objeto BaseQuery en SQLAlchemy, que es devuelto por filter_by .

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

La ventaja de utilizar la update en lugar de cambiar la entidad se produce cuando hay muchos objetos que actualizar.

Si desea dar permiso de add_user a todos los admin ,

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

Observe que filter_by toma los argumentos de las palabras clave (use solo uno = ) en lugar del filter que toma una expresión.

Esto no funciona si modifica un atributo decapado del modelo. Los atributos decapados se deben reemplazar para activar las actualizaciones:

 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 '' % 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} 

Solo asignando el valor y confirmándolos funcionará para todos los tipos de datos, excepto los atributos JSON y Pickled. Dado que el tipo de decapado se explica más arriba, anotaré una forma ligeramente diferente pero fácil de actualizar los 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 

Digamos que el modelo es como el de arriba.

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

Esto agregará al usuario a la base de datos MySQL con datos {“país”: “Sri Lanka”}

La modificación de los datos será ignorada. Mi código que no funcionó es el siguiente.

 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() 

En lugar de pasar por el doloroso trabajo de copiar el JSON a un nuevo dictado (no asignarlo a una nueva variable como la anterior), que debería haber funcionado, encontré una forma sencilla de hacerlo. Hay una forma de marcar el sistema que JSON ha cambiado.

A continuación se muestra el código de trabajo.

 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() 

Funcionó como por arte de magia. Hay otro método propuesto junto con este método aquí. Espero haber ayudado a alguien.