Python 使用NDBs ComputedProperty计算另一个模型';通过祖先查询创建对象

Python 使用NDBs ComputedProperty计算另一个模型';通过祖先查询创建对象,python,google-app-engine,app-engine-ndb,Python,Google App Engine,App Engine Ndb,我正在利用NDBs ComputedProperty和祖先查询来计算与特定过滤器匹配的另一个模型的对象。ComputedProperty如下所示: class Goal(ndb.Model): various_attributes = various_properties @ndb.ComputedProperty def count_active_actions(self): return Action.query(ancestor=self.key).

我正在利用NDBs ComputedProperty和祖先查询来计算与特定过滤器匹配的另一个模型的对象。ComputedProperty如下所示:

class Goal(ndb.Model):
    various_attributes = various_properties
    @ndb.ComputedProperty
    def count_active_actions(self):
        return Action.query(ancestor=self.key).filter(
                Action.status=='active').count()

class Action(ndb.Model):
    status = ndb.StringProperty(choices=(
            'not started', 'active', 'completed', 'on hold'))
    various_attributes = various_properties
    @ndb.ComputedProperty(
    def count_active_tasks(self):
        return Task.query(ancestor=self.key).filter(
                Task.status=='active').count()

class Task(ndb.Model):
    status = ndb.StringProperty(choices=(
            'not started', 'active', 'completed', 'on hold'))
    various_attributes = various_properties
action = Action(parent=goal.key, various_other_properties = various_other_values)
action.put()
当我创建一个
目标
对象时,我不会将任何内容存储为其父对象请注意,我在目标上的ComputedProperty与在操作上的ComputedProperty相似。在编写目标时执行goal.put()时,我没有收到任何错误。

但是,在创建动作对象时,我将父对象存储为
goal.key
,如下所示:

class Goal(ndb.Model):
    various_attributes = various_properties
    @ndb.ComputedProperty
    def count_active_actions(self):
        return Action.query(ancestor=self.key).filter(
                Action.status=='active').count()

class Action(ndb.Model):
    status = ndb.StringProperty(choices=(
            'not started', 'active', 'completed', 'on hold'))
    various_attributes = various_properties
    @ndb.ComputedProperty(
    def count_active_tasks(self):
        return Task.query(ancestor=self.key).filter(
                Task.status=='active').count()

class Task(ndb.Model):
    status = ndb.StringProperty(choices=(
            'not started', 'active', 'completed', 'on hold'))
    various_attributes = various_properties
action = Action(parent=goal.key, various_other_properties = various_other_values)
action.put()
写入操作时,将执行
ComputedProperty
查询,如果操作尚未完全写入,则操作的
id
尚未分配,因此为
None

我收到的错误是:

BadValueError: Expected complete Key, got Key('Goal', '##########', 'Action', None)
鉴于我认为幕后正在发生的事情,这种行为是有道理的。然而,我假设我遗漏了一些东西或者错误地处理了这个问题,因为在我看来这是一个常见的用例

我期望的目标是使父对象的属性表示符合特定条件的子对象的计数,并将父对象的键作为其祖先


有没有更好的方法来实现这一点?还是有什么明显的东西我遗漏了

在某些情况下,您试图用不完整的祖先密钥保存实体。(祖先可能还没有被放进去。)。我不会用计算属性来解决你的问题。很有可能在这一过程中,您会遇到死线超出的错误(正面请求限制为60秒),然后put将失败。那你怎么办?这种方法不太可能扩展或处理停机。我个人会将count\u active\u tasks作为一个整数属性,每次你采取行动时,启动一个任务来计算值。