sqlalchemy:如何阻止特定列上的更新

sqlalchemy:如何阻止特定列上的更新,sqlalchemy,Sqlalchemy,我有一个声明性映射: 类用户(基本): 用户名=列(Unicode(30),unique=True) 我如何告诉sqlalchemy此属性不能修改? 我想出的解决办法有点老套: 来自werkzeug.utils导入缓存的\u属性 #普通的@property也能工作 类用户(基本): _用户名=列('username',Unicode(30),unique=True) @缓存的不动产 def用户名(自我): 返回self.\u用户名 def uuu init uuuu(self,username

我有一个声明性映射:

类用户(基本):
用户名=列(Unicode(30),unique=True)
我如何告诉sqlalchemy此属性不能修改? 我想出的解决办法有点老套:

来自werkzeug.utils导入缓存的\u属性
#普通的@property也能工作
类用户(基本):
_用户名=列('username',Unicode(30),unique=True)
@缓存的不动产
def用户名(自我):
返回self.\u用户名
def uuu init uuuu(self,username,**kw):
超级(用户,自我)。\uuuuu初始功率(**kw)
self.\u username=用户名

在数据库列权限级别上执行此操作将不起作用,因为并非所有数据库都支持此操作。

我建议使用以下方法来保护列不受修改:

在设置任何属性时,首先使用hook

在上述情况下,
Base
declarative的所有表中的所有列都将被钩住,所以您需要以某种方式存储关于是否可以修改列的信息。例如,您可以继承sqlalchemy.Column类向其添加一些属性,然后在钩子中检查属性

class列(sqlalchemy.Column):
定义初始化(self,*args,**kwargs):
self.readonly=kwargs.pop(“readonly”,False)
超级(列,自我)。\uuuuu初始化(*args,**kwargs)
#局部肾盂无检查
@事件。侦听(基本“属性工具”)
def配置侦听器(类、键、指令):
“”“每当检测类上的属性时,就会调用此事件”“”
如果不是hasattr(inst.property,“columns”):
返回
#局部肾盂无检查
@事件侦听(inst,“set”,retval=True)
def set_列_值(实例、值、旧值、启动器):
“”“每当检测的属性上出现“set”时,就会调用此事件”“”
logging.info(“%s:%s->%s”%(inst.property.columns[0],oldvalue,value))
column=inst.property.columns[0]
#如果没有上升错误,可以修改列上的复选框
如果不是column.readonly:
引发运行时错误(“无法更改列%s!”%Column.name)
返回值
要钩住具体属性,可以采用下一种方法(不需要向列添加属性):

#标准装饰风格
@侦听(SomeClass.someu属性“set”)
def接收设置(目标、值、旧值、启动器):
“侦听“设置”事件”
# ... (事件处理逻辑)。。。
是关于SQLAlchemy事件的指南

我建议的第二种方法是使用标准Python属性或SQLAlchemy
hybrid_属性,如您在问题中所示,但使用这种方法会导致代码增长


另外,我假设压缩的方法是将属性添加到列并钩住所有设置事件。

您可以使用
验证
SQLAlchemy功能

sqlalchemy.orm导入验证中的

...
类用户(基本):
...
@验证('用户名')
def验证_用户名(self、key、value):
如果self.username:#字段已存在
raise VALUERROR('无法修改用户名')
返回值
参考资料:

谢谢,“hook concrete attributes”五层衬里正是我要找的。