python - tutorial - model sqlalchemy
Flask-SQLalchemy actualiza la informaciĆ³n de una fila (4)
¿Cómo puedo actualizar la información de una fila?
Por ejemplo, me gustaría modificar la columna del nombre de la fila que tiene el ID 5.
Esto no funciona si modifica un atributo escamado del modelo. Los atributos escabechados deben reemplazarse para activar 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 ''<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}
Hay una update
método en el objeto BaseQuery en SQLAlchemy, que se devuelve mediante filter_by
.
admin = User.query.filter_by(username=''admin'').update(dict(email=''[email protected]'')))
db.session.commit()
La ventaja de utilizar la update
sobre el cambio de la entidad se produce cuando hay muchos objetos para actualizar.
Si quieres otorgar permiso de add_user
a todos los admin
,
rows_changed = User.query.filter_by(role=''admin'').update(dict(permission=''add_user''))
db.session.commit()
Tenga en cuenta que filter_by
toma argumentos de palabra clave (use solo uno =
) en lugar de filter
que toma una expresión.
Solo asignar el valor y comprometerlos funcionará para todos los tipos de datos, pero JSON y los atributos de Pickled. Como el tipo escabechado se explica más arriba, anotaré una manera 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 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 dict (no asignarlo a una nueva variable como la anterior), que debería haber funcionado, encontré una forma sencilla de hacerlo. Hay una manera de marcar el sistema que los JSON han cambiado.
A continuación está 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 here Espero haber ayudado a alguien.
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 misma. Entonces, db.session.commit()
.
Por ejemplo:
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á basado en SQLAlchemy, así que asegúrate de consultar también los documentos de SQLAlchemy .