Flask-SQLalchemy更新行的信息

poc*_*chi 95 python sqlalchemy flask-sqlalchemy

如何更新行的信息?

例如,我想更改id为5的行的name列.

Mar*_*eth 174

使用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()
Run Code Online (Sandbox Code Playgroud)

Flask-SQLAlchemy基于SQLAlchemy,因此请务必查看SQLAlchemy文档.

  • 这与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)以获取更多信息. (10认同)
  • 谢谢马克。另一件事。我已经看到它像这样'db.add(user)'然后是'dv.session.commit()'。为什么两者都有效?有什么区别? (2认同)

Dev*_*evi 81

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

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

update当有许多对象需要更新时,使用过度更改实体的优势就来了.

如果你想给add_user所有的admins,

rows_changed = User.query.filter_by(role='admin').update(dict(permission='add_user'))
db.session.commit()
Run Code Online (Sandbox Code Playgroud)

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


小智 15

如果修改模型的pickle属性,则此方法无效.应该替换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}
Run Code Online (Sandbox Code Playgroud)


Har*_*ips 6

只需分配值并提交它们将适用于所有数据类型,但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
Run Code Online (Sandbox Code Playgroud)

让我们说模型就像上面那样.

user = User("Jon Dove", {"country":"Sri Lanka"})
db.session.add(user)
db.session.flush()
db.session.commit()
Run Code Online (Sandbox Code Playgroud)

这将使用数据{"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()
Run Code Online (Sandbox Code Playgroud)

而不是经历将JSON复制到新dict(不将其分配给上面的新变量)的痛苦工作,这应该有效,我发现了一种简单的方法.有一种方法可以标记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()
Run Code Online (Sandbox Code Playgroud)

这就像一个魅力.在这里提出了另一种方法, 希望我帮助了一些方法.

  • `db.session.merge(user)` 添加此代码对我有用,仅供参考。 (3认同)