Flask-SQL 炼金术更新行信息

如何更新行的信息?

例如,我想更改 id 为5的行的名称列。

266174 次浏览

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

SQLAlchemy 中有一个方法 update on BaseQuery 对象,由 filter_by返回。

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

当有许多对象需要更新时,使用 update优于更改实体。

如果你想给所有的 admin授予 add_user权限,

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

注意,filter_by接受关键字参数(只使用一个 =) ,而 filter接受表达式。

如果修改模型的 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}

只要分配值并提交它们,除了 JSON 和 Pickled 属性之外的所有数据类型都可以工作。由于 pickle 类型在上面已经解释过了,我将记下一种稍微不同但是容易的更新 JSONs 的方法。

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 复制到一个新的 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()

这招真管用。 同时还提出了另一种方法 给你 希望我帮到了什么人。

Py 定义序列化器

def default(o):
if isinstance(o, (date, datetime)):
return o.isoformat()


def get_model_columns(instance,exclude=[]):
columns=instance.__table__.columns.keys()
columns=list(set(columns)-set(exclude))
return columns


class User(db.Model):
__tablename__='user'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
.......
####


def serializers(self):
cols = get_model_columns(self)
dict_val = {}
for c in cols:
dict_val[c] = getattr(self, c)
return json.loads(json.dumps(dict_val,default=default))

在 RestApi 中,我们可以通过将 json 数据传递到 update query 来动态更新记录:

class UpdateUserDetails(Resource):
@auth_token_required
def post(self):
json_data = request.get_json()
user_id = current_user.id
try:
instance = User.query.filter(User.id==user_id)
data=instance.update(dict(json_data))
db.session.commit()
updateddata=instance.first()
msg={"msg":"User details updated successfully","data":updateddata.serializers()}
code=200
except Exception as e:
print(e)
msg = {"msg": "Failed to update the userdetails! please contact your administartor."}
code=500
return msg

我正在寻找一些比@Ramesh 的回答稍微不那么打扰人的东西(这很好) ,但仍然是动态的。下面是将更新方法附加到数据库的解决方案。模型对象。

您传入一个字典,它将只更新您传入的列。

class SampleObject(db.Model):
id = db.Column(db.BigInteger, primary_key=True)
name = db.Column(db.String(128), nullable=False)
notes = db.Column(db.Text, nullable=False)


def update(self, update_dictionary: dict):
for col_name in self.__table__.columns.keys():
if col_name in update_dictionary:
setattr(self, col_name, update_dictionary[col_name])


db.session.add(self)
db.session.commit()

然后在一条路线上你可以做

object = SampleObject.query.where(SampleObject.id == id).first()
object.update(update_dictionary=request.get_json())

更新烧瓶中的柱子

admin = User.query.filter_by(username='admin').first()
admin.email = 'my_new_email@example.com'
admin.save()

要使用 update方法 (它在会话之外更新主菜),你必须按如下步骤查询对象:

query = db.session.query(UserModel)
query = query.filter(UserModel.id == user_id)
query.update(user_dumped)
db.session.commit()