2011-07-14 41 views

回答

109

的行的名稱列使用tutorial shown in the Flask-SQLAlchemy documentation檢索的對象。一旦你有你想改變的實體,改變實體本身。然後,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(用戶)'然後'dv.session.commit()'。爲什麼這兩個工作?有什麼區別? – pocorschi

+8

這與SQLAlchemy中臨時對象,分離對象和附加對象之間的差異有關(請參閱http://www.sqlalchemy.org/docs/orm/session.html#what-does-the-session-do)。另外,請閱讀Michael Bayer對郵件列表的評論(http://groups.google.com/group/sqlalchemy/browse_thread/thread/e38e2aba57aeed92?pli=1)瞭解更多信息。 –

+1

如果您在閱讀後仍然對差異感到困惑,請考慮提出另一個問題。 –

50

SQLAlchemy中的BaseQuery對象上有一個方法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這需要一個表達式關鍵字參數(只有一個=使用)。

13

如果修改了模型的pickle屬性,這不起作用。醃製屬性應該以觸發更新替代:

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和醃屬性工作。由於醃過的類型在上面解釋過,所以我會記下一個稍微不同但簡單的方法來更新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到一個新的字典(不是如上分配給新的變量),它應該有工作,我發現一個簡單的方法來做到這一點的痛苦去工作的。有一種方法可以標記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() 

這工作就像一個魅力。 還有另一種方法與此方法一起提出here 希望我已經幫了一些人。