3

我有一个ComputedProperty内部 aStructuredProperty在首次创建对象时不会更新。

当我创建对象时address_components_ascii没有保存。该字段在数据存储查看器中根本不可见。但是,如果我get()然后立即put()再次(即使没有更改任何内容),ComputedProperty则按预期工作。该address_components字段正常工作。

我曾尝试清除数据库,并删除整个数据库文件夹,但没有成功。

我在 Windows 7 上使用本地开发服务器。我尚未在 GAE 上对其进行测试。


这是代码:

class Item(ndb.Model):
    location = ndb.StructuredProperty(Location)

内部位置类:

class Location(ndb.Model):
    address_components = ndb.StringProperty(repeated=True)  # array of names of parent areas, from smallest to largest
    address_components_ascii = ndb.ComputedProperty(lambda self: [normalize(part) for part in self.address_components], repeated=True)

归一化函数

def normalize(s):
    return unicodedata.normalize('NFKD', s.decode("utf-8").lower()).encode('ASCII', 'ignore')

字段示例address_components

[u'114B', u'Drottninggatan', u'Norrmalm', u'Stockholm', u'Stockholm', u'Stockholms l\xe4n', u'Sverige']

address_components_ascii字段,在第二个之后put()

[u'114b', u'drottninggatan', u'norrmalm', u'stockholm', u'stockholm', u'stockholms lan', u'sverige']
4

3 回答 3

2

真正的问题似乎是 GAE 调用相对于周围调用_prepare_for_put()的顺序。StructuredProperty_pre_put_hook()Model

我正在写信address_componentsItem._pre_put_hook(). 我假设 GAE在调用on之前计算了ComputedPropertythe 。从 ComputedProperty 读取会导致重新计算其值。StructuredProperty_pre_put_hook()Item

我将此添加到末尾_pre_put_hook()

# quick-fix: ComputedProperty not getting generated properly
# read from all ComputedProperties, to compute them again before put
_ = self.address_components_ascii

我将返回值保存到一个虚拟变量以避免 IDE 警告。

于 2015-05-17T11:19:16.827 回答
1

我刚刚在开发服务器上尝试了这段代码并且它工作正常。计算属性在 put 之前和之后都可以访问。

from google.appengine.ext import ndb

class TestLocation(ndb.Model):
  address = ndb.StringProperty(repeated=True)
  address_ascii = ndb.ComputedProperty(lambda self: [
    part.lower() for part in self.address], repeated=True)

class TestItem(ndb.Model):
  location = ndb.StructuredProperty(TestLocation)

item = TestItem(id='test', location=TestLocation(
  address=['Drottninggatan', 'Norrmalm']))
assert item.location.address_ascii == ['drottninggatan', 'norrmalm']
item.put()
assert TestItem.get_by_id('test').location.address_ascii == [
  'drottninggatan', 'norrmalm']
于 2015-05-17T06:37:50.247 回答
0

这似乎是ndb. 简单地做一个,put()然后是一个get(),另一个put()工作。它速度较慢,但​​仅在第一次创建对象时才需要。

我添加了这个方法:

def double_put(self):
        return self.put().get().put()

这是put().

当我put()调用一个新对象MyObject.double_put()而不是MyObject.put().

于 2015-05-15T23:07:37.610 回答