Flask-SQLalchemy更新行的信息


Answers:


205

使用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文档


2
谢谢马克。另一件事。我已经看到它像这样'db.add(user)'然后是'dv.session.commit()'。为什么两者都起作用?有什么区别?
pocorschi 2011年

11
这与SQLAlchemy中的临时对象,分离对象和附加对象之间的差异有关(请参阅sqlalchemy.org/docs/orm/session.html#what-does-the-session-do)。另外,请阅读邮件列表(groups.google.com/group/sqlalchemy/browse_thread/thread/…)上Michael Bayer的评论,以获取更多信息。
Mark Hildreth'7

1
如果您在阅读完这些内容后仍然对这些差异感到困惑,请考虑问另一个问题。
马克·希尔德斯

如果列数据类型为json,请使用以下方法。bashelton.com/2014/03/…–
Aram

@MarkHildreth我无法将日期时间值更新到该字段,该怎么办?列是uesd_at = db.Column(db.DateTime)我刚刚运行的,obj.used_at = datetime.datetime.now() db.session.commit()但未将值设置为该字段。
Rukeith '18 -10-30

96

updateSQLAlchemy中的BaseQuery对象有一个方法,由返回filter_by

admin = User.query.filter_by(username='admin').update(dict(email='my_new_email@example.com')))
db.session.commit()

update当要更新的对象很多时,使用更改实体的优势就来了。

如果您想add_user授予所有admins 权限,

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

注意,filter_by使用关键字参数(仅使用一个=),而不是filter使用表达式。


1
在第一个查询中,结果命名为admin,由于结果将是更新的行数,因此可能会产生误导。是不是
Vikas Prasad

并有一种方法可以User通过查询获取受影响的项目,而不是受影响的用户数量?
Vikas Prasad

匹配
Vikas Prasad

18

如果您修改模型的腌制属性,这将不起作用。腌制的属性应被替换以触发更新:

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
在这种情况下最好的方法是什么?
坎普塔,2013年

您必须复制data并重新分配它。
sas 2009年

@sas是什么意思?
Mote Zart '19

您需要复制并分配给data属性以触发更新机制。请看下面的答案:user.data = data
sas

9

仅分配值并提交它们将适用于除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()

这就像一个魅力。这里还建议了另一种方法 希望对我有帮助。


2
db.session.merge(user)添加此代码对我有用,仅供参考。
杰夫·布鲁梅尔
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.