2011-07-14 68 views

答えて

109

tutorial shown in the Flask-SQLAlchemy documentationを使用してオブジェクトを取得し、IDを有する行の名前列を変更したいです。エンティティを変更したら、エンティティ自体を変更します。次に、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() 

フラスコSQLAlchemyの

はSQLAlchemyのに基づいているので、同様 SQLAlchemy Docsをチェックしてください。

+1

ありがとうございました。もう一つのこと。私はこれを 'db.add(user)'と 'dv.session.commit()'のようにしてみました。なぜ両方とも機能するのですか?違いは何ですか? – pocorschi

+8

これは、SQLAlchemyの一時オブジェクト、切り離されたオブジェクト、および添付オブジェクトの違いと関係があります(http://www.sqlalchemy.org/docs/orm/session.html#what-does-the-session-doを参照)。また、マイケルバイエルのメーリングリストに関するコメント(http://groups.google.com/group/sqlalchemy/browse_thread/thread/e38e2aba57aeed92?pli=1)をご覧ください。 –

+1

そこを読んだ後でも差異が混乱している場合は、別の質問をすることを検討してください。 –

50

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

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

更新する多くのオブジェクトがある場合、エンティティを変更する上でupdateを使用することの利点が付属しています。

あなたは、すべてのadmin sの式を取りfilterとは対照的に、filter_byは(一つだけ=を使用)キーワード引数を取ること

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

お知らせをadd_user許可を与えたい場合。

13

モデルのpickled属性を変更すると、これは機能しません。ピクルスの属性は更新をトリガーするために交換する必要があります:

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} 
+1

そのような場合の最善のアプローチは何ですか? – kampta

+0

あなたは 'data'をコピーしてそれを再割り当てする必要があります。 – sas

3

だけで値を代入し、それらはすべてのデータ型が、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データベースにユーザを追加します{「国」:「スリランカ」}

変更データは無視されます。私のコードがうまくいかなかったのは以下の通りです。代わりに、私はそれを行うための簡単な方法を発見し働いているはずの新しいdictの(上記のように、新たな変数に代入せず)にJSONをコピーする痛みを伴う仕事を経由の

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が変更されたというシステムにフラグを立てる方法があります。

以下は作業コードです。

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

これは魅力的でした。 この方法と一緒に提案されたもう1つの方法があります。here 私はいくつかを手伝ってくれました。

関連する問題