【问题标题】:Why does my use of NDB's `populate()` not accept `id` or `parent`, but only `key`?为什么我使用 NDB 的 `populate()` 不接受 `id` 或 `parent`,而只接受 `key`?
【发布时间】:2015-10-15 11:39:59
【问题描述】:

我想创建一个实体对象,在它构建之后,在将它写入数据存储之前,我想设置父对象和 id。

根据App Engine docs,构造函数接受这些关键字参数: - id - key - parent

您无法轻松定义名为“key”、“id”、“parent”或 “命名空间”。例如,如果您在构造函数中传递 key="foo" 或 populate() 调用,它设置实体的键,而不是属性属性 命名为“钥匙”。

对于populate(),它表示它将接受与构造函数相同的关键字参数。但是,我似乎做错了什么,因为唯一有效的关键字参数是key。使用 id 和/或 parent 会出错。

class Foo(ndb.Model):
    pass

foo = Foo()
foo.populate(key=ndb.Key('Bar', 1, 'Foo', 123))
foo.key == ndb.Key('Bar', 1, 'Foo', 123)  # True

当我改为使用关键字parent...

f.populate(parent=ndb.Key('Bar', 1))

...我得到了这个回溯:

Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/model.py", line 2960, in _populate
    self._set_attributes(kwds)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/model.py", line 2970, in _set_attributes
    prop = getattr(cls, name)  # Raises AttributeError for unknown properties.
AttributeError: type object 'Foo' has no attribute 'parent'

或者有时这个(不确定是什么造成的不同):

File "<console>", line 1, in <module>
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/model.py", line 2960, in _populate
    self._set_attributes(kwds)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/model.py", line 2972, in _set_attributes
    raise TypeError('Cannot set non-property %s' % name)
TypeError: Cannot set non-property parent

如果我使用id...

f.populate(id=123)

我又得到一个属性错误:

Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/model.py", line 2960, in _populate
    self._set_attributes(kwds)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/model.py", line 2970, in _set_attributes
    prop = getattr(cls, name)  # Raises AttributeError for unknown properties.
AttributeError: type object 'Foo' has no attribute 'id'

我上面的所有populate() 示例不都应该与任何关键字参数一起使用吗?

我知道,我只能使用 key 来达到与 parentid 一起使用的效果,但我想知道我在这里缺少什么。

【问题讨论】:

    标签: python google-app-engine app-engine-ndb google-cloud-datastore


    【解决方案1】:

    parentKey 在使用祖先路径时的属性。构造函数接受它是为了方便,但由于它不是它自己的属性,populate() 会抱怨它不存在。 id 也是如此。构造函数使用id 构造一个Key,使用_get_kind()id 的值。

    一个例子值 1000 cmets。看看如何使用idparent 构造key

    >>> from google.appengine.ext import ndb
    >>>>
    >>> class Foo(ndb.Model):
    ...     pass
    ...
    >>> foo = Foo(id=123, parent=ndb.Key('Bar', 1))
    >>> foo.key
    Key('Bar', 1, 'Foo', 123)
    >>> foo.id
    Traceback (most recent call last):
      File "<console>", line 1, in <module>
    AttributeError: 'Foo' object has no attribute 'id'
    >>> foo.parent
    Traceback (most recent call last):
      File "<console>", line 1, in <module>
    AttributeError: 'Foo' object has no attribute 'parent'
    

    【讨论】:

      【解决方案2】:

      文档可能对此问题不够清楚,但您只能使用populate 来更新模型的属性(实际数据)。

      看源码就清楚了,比如模型构造函数的this line

      注意:你不能定义一个名为 key 的属性; .key 属性始终引用实体的键。但是您可以定义名为 id 或 parent 的属性。后者的值不能通过构造函数传递,但可以在实体创建后赋值给实体属性。

      建议我们可以使用idparent 作为属性/属性,因此populate 调用将尝试设置它们。

      当我们到达 populate implementation 时,它会变得更加清晰,其中内联文档为您的确切问题提供了规定:

      每个关键字参数将用于设置相应的属性。关键字必须引用有效的属性名称。这类似于将关键字参数传递给 Model 构造函数,只是没有为 key、id 或 parent 做任何规定。

      也许应该用这些信息更新文档以避免混淆。我自己从来没有遇到过这个问题,可能是因为我一直遵循“仅在实例化模型时设置密钥”的建议,但是我找不到该语句的引用;我把它作为一个经验法则,并且我的印象是之后尝试分配它应该会在任何地方引发异常。

      好像前面的引用还不够,看看构造函数中的this line

      self._key = _validate_key(key, entity=self)
      

      您不会在其他任何地方找到它,因此这是唯一一个 [正确] 分配给模型的键实例(正如您可以想象的那样,populate 仅迭代和设置值)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-12-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-22
        • 1970-01-01
        • 2023-03-07
        • 2016-03-24
        相关资源
        最近更新 更多