2011-07-14 66 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 希望我已经帮了一些人。