- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在从事一个项目,该项目需要对创建的每个模型进行通用定制。迄今为止,我完成大部分工作的方式是通过模型继承。这是我的代码块,可以给您一个更好的主意:
app.core.dba.mixins:
class AuditExtension(MapperExtension):
"""
AuditExtension enforces the audit column values, and ensures any interaction with
SQLAlchemy cannot override the values
"""
def before_insert(self, mapper, connection, instance):
instance.created_dt = datetime.utcnow()
instance.created_by = audit_session_user()
instance.updated_dt = datetime.utcnow()
instance.updated_by = audit_session_user()
def before_update(self, mapper, connection, instance):
# Never update the created columns
instance.created_dt = instance.created_dt
instance.created_by = instance.created_by
instance.updated_dt = datetime.utcnow()
instance.updated_by = audit_session_user()
class AuditColumns(object):
""" Generate the column schema for simple table level auditing. """
created_dt = Column(DateTime,
default=datetime.utcnow(),
nullable=False)
created_by = Column(String(64),
#ForeignKey('operators.username', ondelete="RESTRICT"),
nullable=False)
updated_dt = Column(DateTime,
default=datetime.utcnow(),
nullable=False,
onupdate=datetime.utcnow())
updated_by = Column(String(64),
#ForeignKey('operators.username', ondelete="RESTRICT"),
nullable=False)
__mapper_args__ = {
'extension': AuditExtension()}
然后我的模型继承 AuditColumns:
class ObjectTypes(Base, AuditColumns):
__tablename__ = 'object_types'
id = Column(BigInteger, primary_key=True)
name = Column(String, nullable=False, unique=True)
def __repr__(self):
return self.name
我的问题是;只要操作包含在 flask 应用程序和 SQLAlchemy 中,我强制审计数据的解决方案就可以工作——这不会阻止任何具有数据库访问权限的人更新值。
因此,我现在需要在每个继承 AuditColumns 的模型上实现一个触发器。我找到这篇文章 Sqlalchemy mixins / and event listener - 它描述了用于 before_insert/update 的方法(我以前使用过),但没有用于“after_create”。
现在,我已将其添加到我的 mixins 文件代码中(直接在我上面的审计代码之后:
trig_ddl = DDL("""
CREATE TRIGGER tr_audit_columns BEFORE INSERT OR UPDATE
ON test_table
FOR EACH ROW EXECUTE PROCEDURE
ss_test();
""")
event.listen(AuditColumns, 'after_create', trig_ddl)
但是,当我运行一个测试用例时:
Base.metadata.drop_all(db.get_engine(app))
Base.metadata.create_all(db.get_engine(app))
我收到以下错误:
File "D:\Devel\flask-projects\sc2\app\core\dba\mixins.py", line 59, in <module>
event.listen(AuditColumns, 'after_create', trig_ddl)
File "D:\Devel\flask-projects\env\lib\site-packages\sqlalchemy\event.py", line 43, in listen
(identifier, target))
sqlalchemy.exc.InvalidRequestError: No such event 'after_create' for target '<class 'app.core.dba.mixins.AuditColumns'>'
我猜这是因为它还不是一张 table ;但是我如何为表创建全局定义一个事件监听器,它将执行这种类型的命令?
我知道我必须使 trig_ddl 动态化(我认为这不会太难,但我至少需要弄清楚它的全局元素)。
基本上,我不希望人们必须在每个模型中手动写入此事件,因为它显然与这些审计列相关联。
任何朝着正确方向的插入都会很棒。
最佳答案
好吧,你需要在这里搭载事件,这样你才能到达那个Table
:
@event.listens_for(AuditColumns, "instrument_class", propagate=True)
def instrument_class(mapper, class_):
if mapper.local_table is not None:
trigger_for_table(mapper.local_table)
def trigger_for_table(table):
trig_ddl = DDL("""
CREATE TRIGGER tr_%s_audit_columns BEFORE INSERT OR UPDATE
ON %s
FOR EACH ROW EXECUTE PROCEDURE
ss_test();
""" % (table.name, table.name))
event.listen(table, 'after_create', trig_ddl)
AuditColumms
的任何子类都已映射,mapper.local_table
将已经存在(class.__table__
也将存在,同样的事情),您在该点应用 DDL 事件。
关于python - 所有模型的 SQLAlchemy 事件 after_create,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17543626/
我有以下带有日志信息的代码。 global_id 值设置为 attr_accessible 这个有效 代码: Location.update(model[:id],:global_id => gi[:
创建 Hook 后的以下内容未成功设置 gdoc 键。我们必须改用 self.write_attribute。我是不是想做一些蠢事? class GoogleDoc field :gdoc_key
在 Rails 中进行测试一直是一个谜,如果可能的话我会避免,但我正在将一个人们愿意付费的生产应用程序放在一起,所以我真的需要测试。这个问题让我很生气,因为测试失败了,但是当我在控制台中(在测试和开发
class Model < ActiveRecord::Base after_create :set_slug def set_slug update_column(:slug, to
这是我正在使用的模型,我已将其简化为最简单的形式,但仍然无法满足我的示例: class User self.id, :name => "current") List.create(:user
我有用户、组和成员资格。我使用成员资格联接表在用户和组之间建立了一个 has_many through 关系。我想要做的是设置一个 after_create 回调,每当用户创建一个新组时,该回调将一条
我无法在 after_create 回调中访问我的模型的属性......似乎我应该能够对吗? Controller : @dog = Dog.new(:color => 'brown', :gende
假设我有用户、帐户和产品模型。我想要所有这些模型的通用 after_create 回调,比如 log_creation。 我该怎么做? 最佳答案 您可以拥有一个GenericModule 并将其包含在
我有一个简单的情境设置,以便学习使用 FactoryGirl 进行测试。 银行有很多交易。每次创建交易时,它都应该从银行的总额中减去交易金额。 代码如下: # Bank.rb - Has many t
我有两个不同的 after_create 回调。我只希望在创建的记录中存在一个字段时运行一个 我知道怎么做,但我不太明白语法 #rental.rb after_create :delete_booki
我正在从事一个项目,该项目需要对创建的每个模型进行通用定制。迄今为止,我完成大部分工作的方式是通过模型继承。这是我的代码块,可以给您一个更好的主意: app.core.dba.mixins: clas
我想为每个用户的公司创建一个默认的类别,在他创建一个之后。 详细说明, User has_many :companies Company belongs_to :user has_many
我的模型中有代码。 class Foo ).create({:id=>18}) expected: 1 time received: 0 times 可能出了什么问题? 最
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 7年前关闭。 Improve thi
我希望ActiveRecord使用回调自动设置一些数据库字段。 class Product < ActiveRecord::Base after_create :set_locale de
我知道 before_create 在对象转换到数据库之前被调用,after_create 在之后被调用。 before_create 将被调用而 after_create 而不是的唯一时间是对象未能
我有两个模型 class Contract true) end end end is_live 是契约(Contract)模型中的 bool 字段。合约在创建时默认为不存在(is_liv
我有一个在创建对象后调用的方法 after_create :send_welcome_email 有没有办法将其限制为某个条件,例如对象的属性值 after_create :send_welcome_
我尝试使用 after_create 回调在 FactoryGirl 中定义 has_many 关系,如/spec/factories/emails.rb 中所示: FactoryGirl.defin
(轨道上的 ruby ) 我有一个注册表单,可以将表单中的数据保存到一个表和另一个表中。我使用 Hook “after_save :process_field_to_another_table”和“a
我是一名优秀的程序员,十分优秀!