为什么我使用NDB的`populate()`不接受`id`或`parent`,而只接受`key`?
我想创建一个实体对象,并在其构建之后,在将其写入数据存储之前,我想要设置父对象和ID。为什么我使用NDB的`populate()`不接受`id`或`parent`,而只接受`key`?
据App Engine docs,构造函数接受以下关键字参数: - id
- key
- parent
You cannot easily define a property named "key", "id", "parent", or "namespace". If you pass, for example, key="foo" in a constructor or populate() call, it sets the entity's key, not a property attribute named "key".
为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
来实现和parent
和id
一样的一样,但是我想知道我在这里错过了什么。
parent
是使用祖先路径时的Key
的属性。构造函数接受它作为一种方便,但由于它不是它自己的属性,populate()
会抱怨它不存在。 id
也是如此。构造函数使用id
构造Key
使用_get_kind()
和值id
。
一个例子值得1000条评论。看看如何用id
和parent
构建一个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'
该问题的文档可能不够清晰,但您只应使用populate
来更新模型的属性(实际数据)。
这是明确的查看源代码,例如this line模型构造:
Note: you cannot define a property named key; the .key attribute always refers to the entity's key. But you can define properties named id or parent. Values for the latter cannot be passed through the constructor, but can be assigned to entity attributes after the entity has been created.
建议我们可以用id
和parent
作为属性/属性,从而populate
通话将尝试设置。
Each keyword argument will be used to set a corresponding property. Keywords must refer to valid property name. This is similar to passing keyword arguments to the Model constructor, except that no provisions for key, id or parent are made.
也许应该文档使用此信息,以避免混乱更新:
一旦我们得到的populate
implementation,其中内联文档有一个规定,您的具体问题,它会变得更加清晰。我自己从来没有遇到过这个问题,也许是因为我一直遵循“在实例化模型时只设置键值”的建议,但是我找不到这个语句的引用;我认为这是一个经验法则,我以为试图在以后分配它应该在任何地方引发例外。
而且好像前面引用还不够,看看this line在构造函数中:
self._key = _validate_key(key, entity=self)
你不会找到其他地方,所以这是被分配的一个关键的唯一实例[正确]到一个模型(你可以想象,populate
只迭代和设置值)。