Google App Engine NDB 创建 __metadata__ 属性
Google App Engine NDB creating __metadata__ properties
我一直在使用 Google App Engine 开发原型库存应用程序。我最近从使用旧的 DB 数据存储库切换到使用新的 NDB 库,这些功能很酷,但是在对我的一个实体进行更改时,NDB 突然插入了一个名为“元数据”在我的实体中。这是实体描述(我所做的更改是添加 "inv_posid" 和 "inv_lastchange" 属性,没什么大不了的):
class Inventory(ndb.Model):
inv_product = ndb.KeyProperty(kind = Product)
inv_prdcr_name = ndb.StringProperty(default="")
inv_product_type = ndb.StringProperty(default="")
inv_product_name = ndb.StringProperty(default="")
inv_product_year = ndb.IntegerProperty(default=0)
inv_count = ndb.IntegerProperty(default=0)
inv_price = ndb.IntegerProperty(default=0)
inv_glass_price = ndb.IntegerProperty(default=0)
inv_bin = ndb.StringProperty(default="")
inv_posid = ndb.StringProperty(default="")
inv_lastchange = ndb.FloatProperty(default=0.0)
通过添加新属性,我打算更改我的查询以使用 "inv_lastchange" 作为过滤器,并且由于 NDB 从不在结果中包含不包含适当 属性 的实体,我想 运行 快速浏览我的数据存储,将属性适当地添加到所有实体。所以,这就是我所做的:
...
@ndb.tasklet
def fixInventory(invitem):
invitem.inv_posid = ""
invitem.inv_lastchange = 0.0
invkey = yield invitem.put_async()
inventory = Inventory.query()
output = inventory.map(fixInventory)
我认为使用 tasklet 看看异步调用是如何工作的会很巧妙。然而,在这样做之后,当我去查看数据存储查看器(在我的本地数据存储上)时,我看到了这个新的“元数据”属性,我只是假设它是NDB 需要的东西,所以我什么都没想。
直到下次我尝试更新我的库存项目时,我收到了这个错误:
File "/Programming/VirtualCellar/server/virtsom.py", line 2118, in get
inventory.put()
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/model.py", line 3432, in _put
return self._put_async(**ctx_options).get_result()
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/tasklets.py", line 326, in get_result
self.check_success()
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/tasklets.py", line 369, in _help_tasklet_along
value = gen.throw(exc.__class__, exc, tb)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/context.py", line 810, in put
key = yield self._put_batcher.add(entity, options)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/tasklets.py", line 369, in _help_tasklet_along
value = gen.throw(exc.__class__, exc, tb)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/context.py", line 343, in _put_tasklet
keys = yield self._conn.async_put(options, datastore_entities)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/tasklets.py", line 455, in _on_rpc_completion
result = rpc.get_result()
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/api/apiproxy_stub_map.py", line 613, in get_result
return self.__get_result_hook(self)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/datastore/datastore_rpc.py", line 1882, in __put_hook
self.check_rpc_success(rpc)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/datastore/datastore_rpc.py", line 1373, in check_rpc_success
raise _ToDatastoreError(err)
BadRequestError: cannot store entity with reserved property name '__metadata__'
这是怎么回事?有什么我忘记在这里做的事吗?感觉“元数据”属性 应该以某种方式隐藏或保护,但它已像常规 属性 一样被添加,这是现在阻止对实体进行任何其他保存。以前有人 运行 看过这个吗?
__metadata__
属性 在实体保存到数据存储时添加到实体,在从数据存储读取时删除。这是在 google/appengine/datastore/datastore_stub_util.py
.
中的 _ToStorageEntity
和 _FromStorageEntity
函数中完成的
可能是内部故障以某种方式破坏了您的实体。
您可以通过从实体实例的 _properties
字典中删除 __metadata__
属性 并保存来恢复。
例如:
for inv in Inventory.query():
del inv._properties['__metadata__']
inv.put()
(可能在尝试此操作之前备份您的本地数据存储文件,以防发生意外)。
所以,根据 snakecharmerb 上面所说的,我开始研究为什么我的数据存储查看器也向我显示 __metadata__
属性,并且它原来我之前下载了一个旧版本的 google App Engine SDK,出于某种原因,我的环境变量仍然指向那个旧版本,即使我已经安装了最新版本的 SDK 几次次。我从我的机器上清除了 google App Engine SDK 的所有痕迹,并从头开始 re-installed SDK,然后 voila! __metadata__
属性消失了离开,在数据存储查看器和我自己的代码中!我目前的假设是 google/appengine/datastore/datastore_stub_util.py
文件的旧版本没有以相同的方式处理 __metadata__
属性。
非常感谢您的帮助!
我一直在使用 Google App Engine 开发原型库存应用程序。我最近从使用旧的 DB 数据存储库切换到使用新的 NDB 库,这些功能很酷,但是在对我的一个实体进行更改时,NDB 突然插入了一个名为“元数据”在我的实体中。这是实体描述(我所做的更改是添加 "inv_posid" 和 "inv_lastchange" 属性,没什么大不了的):
class Inventory(ndb.Model):
inv_product = ndb.KeyProperty(kind = Product)
inv_prdcr_name = ndb.StringProperty(default="")
inv_product_type = ndb.StringProperty(default="")
inv_product_name = ndb.StringProperty(default="")
inv_product_year = ndb.IntegerProperty(default=0)
inv_count = ndb.IntegerProperty(default=0)
inv_price = ndb.IntegerProperty(default=0)
inv_glass_price = ndb.IntegerProperty(default=0)
inv_bin = ndb.StringProperty(default="")
inv_posid = ndb.StringProperty(default="")
inv_lastchange = ndb.FloatProperty(default=0.0)
通过添加新属性,我打算更改我的查询以使用 "inv_lastchange" 作为过滤器,并且由于 NDB 从不在结果中包含不包含适当 属性 的实体,我想 运行 快速浏览我的数据存储,将属性适当地添加到所有实体。所以,这就是我所做的:
...
@ndb.tasklet
def fixInventory(invitem):
invitem.inv_posid = ""
invitem.inv_lastchange = 0.0
invkey = yield invitem.put_async()
inventory = Inventory.query()
output = inventory.map(fixInventory)
我认为使用 tasklet 看看异步调用是如何工作的会很巧妙。然而,在这样做之后,当我去查看数据存储查看器(在我的本地数据存储上)时,我看到了这个新的“元数据”属性,我只是假设它是NDB 需要的东西,所以我什么都没想。
直到下次我尝试更新我的库存项目时,我收到了这个错误:
File "/Programming/VirtualCellar/server/virtsom.py", line 2118, in get
inventory.put()
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/model.py", line 3432, in _put
return self._put_async(**ctx_options).get_result()
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/tasklets.py", line 326, in get_result
self.check_success()
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/tasklets.py", line 369, in _help_tasklet_along
value = gen.throw(exc.__class__, exc, tb)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/context.py", line 810, in put
key = yield self._put_batcher.add(entity, options)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/tasklets.py", line 369, in _help_tasklet_along
value = gen.throw(exc.__class__, exc, tb)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/context.py", line 343, in _put_tasklet
keys = yield self._conn.async_put(options, datastore_entities)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/tasklets.py", line 455, in _on_rpc_completion
result = rpc.get_result()
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/api/apiproxy_stub_map.py", line 613, in get_result
return self.__get_result_hook(self)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/datastore/datastore_rpc.py", line 1882, in __put_hook
self.check_rpc_success(rpc)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/datastore/datastore_rpc.py", line 1373, in check_rpc_success
raise _ToDatastoreError(err)
BadRequestError: cannot store entity with reserved property name '__metadata__'
这是怎么回事?有什么我忘记在这里做的事吗?感觉“元数据”属性 应该以某种方式隐藏或保护,但它已像常规 属性 一样被添加,这是现在阻止对实体进行任何其他保存。以前有人 运行 看过这个吗?
__metadata__
属性 在实体保存到数据存储时添加到实体,在从数据存储读取时删除。这是在 google/appengine/datastore/datastore_stub_util.py
.
_ToStorageEntity
和 _FromStorageEntity
函数中完成的
可能是内部故障以某种方式破坏了您的实体。
您可以通过从实体实例的 _properties
字典中删除 __metadata__
属性 并保存来恢复。
例如:
for inv in Inventory.query():
del inv._properties['__metadata__']
inv.put()
(可能在尝试此操作之前备份您的本地数据存储文件,以防发生意外)。
所以,根据 snakecharmerb 上面所说的,我开始研究为什么我的数据存储查看器也向我显示 __metadata__
属性,并且它原来我之前下载了一个旧版本的 google App Engine SDK,出于某种原因,我的环境变量仍然指向那个旧版本,即使我已经安装了最新版本的 SDK 几次次。我从我的机器上清除了 google App Engine SDK 的所有痕迹,并从头开始 re-installed SDK,然后 voila! __metadata__
属性消失了离开,在数据存储查看器和我自己的代码中!我目前的假设是 google/appengine/datastore/datastore_stub_util.py
文件的旧版本没有以相同的方式处理 __metadata__
属性。
非常感谢您的帮助!