web-dev-qa-db-ja.com

Flask-SQLalchemyは行の情報を更新します

行の情報を更新するにはどうすればよいですか?

たとえば、IDが5の行の名前列を変更したいと思います。

90
pocorschi

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 も確認してください。

171
Mark Hildreth

SQLAlchemyのBaseQueryオブジェクトにupdateというメソッドがあり、filter_byによって返されます。

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

エンティティを変更するよりもupdateを使用する利点は、更新するオブジェクトが多い場合に得られます。

すべてのadminadd_user権限を付与する場合、

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

式をとるfilterとは対照的に、filter_byはキーワード引数を取る(=を1つだけ使用する)ことに注意してください。

78
Devi

モデルのピクルスされた属性を変更する場合、これは機能しません。更新をトリガーするには、漬物の属性を置き換える必要があります。

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

値を割り当ててコミットするだけで、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()

これにより、データ{"country": "Sri Lanka"}を使用して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を新しい辞書にコピーするという苦痛な作業を行う代わりに(上記のように新しい変数に割り当てるのではなく)、うまくいくはずだったので、簡単な方法を見つけました。 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()

これは魅力的でした。この方法と一緒に提案された別の方法があります ここ 私はいくつかを助けたことを願っています。