在使用vars更改db.Model(flask-sqlalchemy)值失败后,我使用
setattr
解决了这个问题,但在阅读文档后仍然没有得到vars
和setattr
之间的区别。
以下是我尝试过的方法
在vars
中失败
代码
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
def set_option_parameters(var, option_keys, options):
for option_key in options:
if option_key in option_keys and options[option_key] is not None:
vars(var)[option_key] = options[option_key]
# setattr(var, option_key, options[option_key])
class Application(db.Model):
id = db.Column(db.BigInteger(), primary_key=True, autoincrement=True)
name = db.Column(db.VARCHAR(20), nullable=False)
...
def __init__(self, options):
option_keys = set(["name"])
set_option_parameters(self, option_keys, options)
def modification(self, options):
modifiable = set(["name"])
set_option_parameters(self, modifiable, options)
vars(var)[option_key] = options[option_key]
在初始化Application
对象时工作良好,但在modification
中失败(name
没有改变)。
日志/测试
我试着在db.session.commit()
之前打印application.__dict__
,它确实被修改了!
application = Application.query.filter_by(id=args["id"]).first()
# args["name"] is not None
app.logger.info(f"Before: {application.__dict__}")
application.modification(args)
app.logger.info(f"After: {application.__dict__}")
db.session.commit()
输出
[2019-02-27 11:22:59,209] INFO in equipmentbaseapplicationhandler: Before:{'_sa_instance_state': <sqlalchemy.orm.state.InstanceState object at 0x7f718ac2b588>, 'id': 9, 'name': 'old_name'}
[2019-02-27 11:22:59,209] INFO in equipmentbaseapplicationhandler: After:{'_sa_instance_state': <sqlalchemy.orm.state.InstanceState object at 0x7f718ac2b588>, 'id': 9, 'name': 'new_name'}
但当我签入mysql时,它不工作。
在setattr
中获得成功
然后我在function set_option_parameters
中更改为setattr(var, option_key, options[option_key])
。
它在初始化和修改中都工作得很好,application.__dict__
的输出也是一样的!
发布于 2019-03-05 04:36:04
用于vars
的From the docs
模块和实例等
对象具有可更新的dict属性;但是,其他对象可能对其dict属性有写入限制(例如,类使用types.MappingProxyType来阻止直接字典更新)。
浏览一下SQLAlchemy源代码(例如,here),在访问时返回some_model.__dict__
的副本是一种常见的模式,而不是返回__dict__
本身。因此,您可能是在更新副本,而不是原始副本。否则,即使字典发生变化,字典也有可能被属性本身覆盖。
setattrs
是正确的模式,而且更明确。
https://stackoverflow.com/questions/54897575
复制相似问题