每次数据存储区实体属性发生变化时如何触发方法调用?
我调查的一种方法是monkeypatching db.Model.put。这涉及到覆盖put方法。虽然这允许我对每个put()作出反应,但是我不清楚如何检测地址属性是否已经改变,因为self.address已经在.put()的开头设置了。
精化:
我有用户,每个用户都有一个物理地址。
class User(db.Model):
...
address = db.StringProperty() # for example "2 Macquarie Street, Sydney"
...
我想验证输入的地址是否正确。为此,我有一个昂贵的地址检查功能(它与远程API联系)和一个布尔字段。
class User(db.Model):
...
address = db.StringProperty()
address_is_valid = db.BooleanProperty(default=False)
def address_has_changed(self):
self.address_is_valid = False
Task(
url = "/check_address", # this would later set .address_is_valid
params = {
'user' : self.key()
}
).add()
...
但是,如何在每次地址更改时触发address_has_changed方法,而不必在任何地方显式调用它?
# It should work when changing an address
some_user = User.all().get()
some_user.address = "Santa Claus Main Post Office, FI-96930 Arctic Circle"
some_user.put()
# It should also work when multiple models are changed
...
db.put([some_user, another_user, yet_another_user])
# It should even work when creating a user
sherlock = User(address='221 B Baker St, London, England')
sherlock.put() # this should trigger address_has_changed
答案 0 :(得分:3)
Hook怎么样?
NDB提供轻量级挂钩机制。通过定义一个钩子,一个 应用程序可以在某种类型的操作之前或之后运行一些代码; 例如,Model可能会在每个get()之前运行一些函数。
from google.appengine.ext import ndb
class Friend(ndb.Model):
name = ndb.StringProperty()
def _pre_put_hook(self):
# inform someone they have new friend
@classmethod
def _post_delete_hook(cls, key, future):
# inform someone they have lost a friend
f = Friend()
f.name = 'Carole King'
f.put() # _pre_put_hook is called
fut = f.key.delete_async() # _post_delete_hook not yet called
fut.get_result() # _post_delete_hook is called
您可以构建一些其他逻辑,以便检查地址的原始版本和新版本,如果它们不同,则运行昂贵的操作,否则只需保存。
答案 1 :(得分:2)
好吧这可能是2年太晚了,但无论如何你总是可以在__init()__
方法中创建类本地变量来存储旧值,而你在调用put方法时比较值从这些旧变量。
class User(db.Model):
def __init__(self, *args, **kwargs):
super(User, self).__init__(*args, **kwargs)
self._old_address = self.address
address = db.StringProperty()
def put(self, **kwargs):
if self._old_address != self.address:
# ...
# do your thing
# ...
super(User, self).put(**kwargs)
答案 2 :(得分:1)
使用python属性。这样可以在实际更改时轻松调用address_has_changed。
答案 3 :(得分:1)
你所引用的Nick的文章或ndb
钩子都没有解决跟踪实体中显式变化的问题,它们只是让它更容易解决。
当你调用put()时,你通常会在pre put hook中调用你的address_is_changed
方法而不是整个代码库。
我有代码使用这些钩子策略来创建记录的每次更改的审计跟踪,
但是,您的代码实际上并未检测到对地址的更改。
您应该考虑更改为ndb
,然后使用post_get hook
(以远离您希望检查的原始属性值 - 例如在会话或请求对象中),然后使用pre_put_hook
要检查当前属性与原始值,看看是否应该采取任何操作,然后调用ddress_has_changed
方法。您可以使用db
(通过遵循Nicks文章)来使用此策略,但是您必须自己做更多繁重的工作。