在NDB中从ComputedProperty函数返回列表的解决方法

4 投票
2 回答
1503 浏览
提问于 2025-04-17 10:25

我正在把我的应用程序转换为使用 NDB。之前我有这样的代码:

@db.ComputedProperty
    def someComputedProperty(self, indexed=False):
      if not self.someCondition:
          return []
      src = self.someReferenceProperty
      list =  src.list1 + src.list2 + src.list3 + src.list4 \
              + [src.str1, src.str2]
      return map(lambda x:'' if not x else x.lower(), list) 

如你所见,我生成列表的方法有点复杂,我更喜欢这样做。但是当我开始转换到 NDB 时,我只是把 @db.ComputedProperty 替换成了 @model.ComputedProperty,结果出现了这个错误:

NotImplementedError: Property someComputedProperty does not support <type 'list'> types.

我在 ext.ndb 的 model.py 文件中看到,ComputedProperty 是从 GenericProperty 继承而来的。在 _db_set_value 里,有几个 if/else 语句根据值的类型来处理,但对 lists 没有处理。

目前,它通过了第一个条件,当我返回一个空列表时就出现了错误。

有没有办法解决这个问题,避免这个错误呢?

2 个回答

13

你需要在NDB中为你的计算属性设置一个叫做repeated=True的标志。我觉得你不能用那种可爱的“@db.ComputedProperty”写法,你得这样写:

def _computeValue(self):
    ...same as before...
someComputedProperty = ComputedProperty(_computeValue, repeated=True, indexed=False)
3

这个功能完全可以放在一个函数里,所以不一定要用到ComputedProperty。只有在你想做一些可能会被查询的计算时,才需要使用计算属性。如果一个ComputedPropertyindexed标志设置为False,那就意味着你不会去查询它,因此其实也不需要把它当作一个属性来用。

def someComputedProperty(self):
  if not self.someCondition:
      return []
  src = self.someReferenceProperty
  list =  src.list1 + src.list2 + src.list3 + src.list4 \
          + [src.str1, src.str2]
  return map(lambda x:'' if not x else x.lower(), list) 

撰写回答