Flask-SQLalchemy обновляет информацию о строках

Как обновить информацию о строке?

Например, я хотел бы изменить столбец имен строки с идентификатором 5.

Ответ 1

Извлеките объект, используя учебник, показанный в документации Flask-SQLAlchemy. Когда у вас есть объект, который вы хотите изменить, измените сам объект. Затем db.session.commit().

Например:

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 основан на SQLAlchemy, поэтому не забудьте также проверить SQLAlchemy Docs.

Ответ 2

В объекте BaseQuery в SQLAlchemy существует метод update, который возвращается filter_by.

admin = User.query.filter_by(username='admin').update(dict(email='[email protected]')))
db.session.commit()

Преимущество использования update над изменением объекта происходит, когда есть много объектов для обновления.

Если вы хотите предоставить разрешение add_user всем admin s,

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

Обратите внимание, что filter_by принимает аргументы ключевого слова (используйте только один =), а не filter, который принимает выражение.

Ответ 3

Это не работает, если вы изменяете маринованный атрибут модели. Маринованные атрибуты должны быть заменены для запуска обновлений:

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}

Ответ 4

Просто присваивание значения и его выполнение будут работать для всех типов данных, но атрибутов JSON и Pickled. Так как маринованный тип объяснен выше, я остановлю немного другой, но простой способ обновления 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

Скажем, модель похожа на выше.

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

Это добавит пользователя в базу данных MySQL с данными { "страна": "Шри-Ланка" }

Изменение данных будет проигнорировано. Мой код, который не работал, выглядит следующим образом.

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

Вместо того, чтобы пройти тяжелую работу по копированию JSON в новый dict (не присваивая его новой переменной, как указано выше), которая должна была работать, я нашел простой способ сделать это. Существует способ отметить систему, которую изменили JSON.

Ниже приведен рабочий код.

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

Это работало как шарм. Существует еще один метод, предложенный вместе с этим методом здесь Надеюсь, я помог кому-то.