问题描述
||
我是Python的新手。我正在尝试弄清楚如何模拟使用PHP和MS-sql编写的现有应用程序,并在Google Apps Engine上重新创建基本的后端功能。
我要执行的操作之一是在MS-sql中模拟某些表上的当前活动,这是一个Insert / Delete / Update触发器,该触发器将当前(更改前)记录的副本插入到审核表,并用日期和时间标记。然后,我可以在以后查询此审计表,以检查记录经过的更改的历史记录。
我在stackoverflow上找到了以下代码:
class HistoryEventFieldLevel(db.Model):
# parent,you don\'t have to define this
date = db.Dateproperty()
model = db.Stringproperty()
property = db.Stringproperty() # Name of changed property
action = db.StringProperty( choices=([\'insert\',\'update\',\'delete\']) )
old = db.Stringproperty() # Old value for field,empty on insert
new = db.Stringproperty() # New value for field,empty on delete
但是,我不确定如何将此代码应用于新数据库中的所有对象。
我应该为每个对象创建get()和put()函数,然后在put()函数中创建此类的子对象并设置其特定属性吗?
解决方法
尽管有些棘手,但这当然是可能的。这里有一些提示可帮助您入门:
覆盖类的
put()
方法是不够的,因为还可以通过调用db.put()
来存储实体,db.put()
不会在正在编写的类上调用任何方法。
如我的博客文章所述,您可以通过修补SDK来调用前/后调用挂钩来解决此问题。
或者,您可以通过实现RPC挂钩在较低级别上进行此操作,如本文另一篇博客文章所述。
将审核记录存储为修改后的实体的子实体是一个好主意,这意味着您可以以事务方式进行操作,尽管这将需要进一步,更困难的更改。
您不需要每个字段都有记录。实体具有自然的序列化格式,即协议缓冲区,您可以简单地将实体作为编码的协议缓冲区存储在审核记录中。如果您在模型级别进行操作,请使用model_to_protobuf将模型转换为协议缓冲区。
以上所有内容在修改记录之后而不是在更改之前更容易应用于存储记录。但是,这不应该成为问题-如果在修改记录之前需要该记录,则只需返回审核日志中的一项即可。
, 我有点与GAE脱节,也没有与我一起进行测试的sdk,因此这里有一些准则可以给您提示您可以做什么。
创建一个元类AuditMeta,您可以在要审计的任何模型中设置该元类
AuditMeta在创建新模型类时应复制带有新名称并附加\“ _ audit \”的类,并且还应复制属性,这对GAE来说有点棘手,因为属性本身就是描述符
在每个这样的类中添加一个put方法,然后在该类上创建一个审计对象并保存,这样,对于tableA中的每一行,tableA_audit中将具有历史记录
例如一个普通的python示例(不带GAE)
import new
class AuditedModel(object):
def put(self):
print \"saving\",self,self.date
audit = self._audit_class()
audit.date = self.date
print \"saving audit\",audit,audit.date
class AuditMeta(type):
def __new__(self,name,baseclasses,_dict):
# create model class,dervied from AuditedModel
klass = type.__new__(self,(AuditedModel,)+baseclasses,_dict)
# create a audit class,copy of klass
# we need to copy attributes properly instead of just passing like this
auditKlass = new.classobj(name+\"_audit\",_dict)
klass._audit_class = auditKlass
return klass
class MyModel(object):
__metaclass__ = AuditMeta
date = \"XXX\"
# create object
a = MyModel()
a.put()
输出:
saving <__main__.MyModel object at 0x957aaec> XXX
saving audit <__main__.MyModel_audit object at 0x957ab8c> XXX
阅读审计跟踪代码(仅200行),以了解他们如何针对django执行此操作