我想创建一个实体对象,在构建之后,在将其写入数据存储区之前,我想设置父元素和id。
根据App Engine docs,构造函数接受以下关键字参数:
- id
- key
- parent
您无法轻松定义名为" key"," id"," parent"或 "命名空间&#34 ;.例如,如果你通过了key =" foo"在构造函数或 populate()调用,它设置实体的键,而不是属性属性 命名为" 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
相同的功能,但我想知道我在这里缺少的内容。< / p>
答案 0 :(得分:3)
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'
答案 1 :(得分:2)
在这个问题上,文档可能不够清晰,但您只应使用populate
来更新模型的属性(实际数据)。
这很清楚源代码,例如模型构造函数的this line:
注意:您无法定义名为key的属性; .key属性始终引用实体的密钥。但您可以定义名为id或parent的属性。后者的值不能通过构造函数传递,但可以在创建实体后分配给实体属性。
建议我们可以使用id
和parent
作为属性/属性,因此populate
调用会尝试设置它们。
一旦我们到达populate
implementation,它就会变得更加清晰,其中内联文档中有一个针对您的确切问题的规定:
每个关键字参数将用于设置相应的属性。关键字必须引用有效的属性名称。这类似于将关键字参数传递给Model构造函数,除了没有为key,id或parent做出规定。
也许应该使用此信息更新文档以避免混淆。我自己从来没有遇到过这个问题,也许是因为我一直遵循“仅在实例化模型时设置密钥”的建议,但是我找不到这个声明的引用;我认为这是一个经验法则,我认为之后尝试分配它应该会引起各地的例外。
如果之前的引用不够,请查看构造函数中的this line:
self._key = _validate_key(key, entity=self)
你不会在其他任何地方找到它,所以这是一个被正确分配给模型的键的唯一实例(你可以想象,populate
只迭代并设置值)。