Flask-SQLalchemy обновляет информацию строки - PullRequest
86 голосов
/ 15 июля 2011

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

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

Ответы [ 4 ]

169 голосов
/ 15 июля 2011

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

Например:

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

76 голосов
/ 20 октября 2011

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

admin = User.query.filter_by(username='admin').update(dict(email='my_new_email@example.com')))
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, который принимает выражение.

15 голосов
/ 13 января 2015

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

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}
5 голосов
/ 25 ноября 2017

Просто присвоение значения и его фиксация будет работать для всех типов данных, кроме атрибутов 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()

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

...