使用endpoint-proto-datastore时设置父键但不设置子键

kei*_*lze 3 python google-app-engine google-cloud-endpoints endpoints-proto-datastore

如何为EndpointsModel设置父/祖先,并让数据存储自动生成实体ID/Key?

我已经尝试调整keys_with_ancestors样本但似乎碰到了一个块,因为它需要指定id和parent.我想做类似的事情,除了只提供父ID或密钥,并由app引擎数据存储自动生成实体ID /密钥.

以下显示了如何使用NDB进行此操作.

class Parent(ndb.Model):
    name = ndb.StringProperty()

class MyModel(ndb.Model):
    attr1 = ndb.StringProperty()
    attr2 = ndb.StringProperty()

p = Parent(name="Jerry")
p_key = p.put()  # or retrieve the key from somewhere else

mod = MyModel(parent=p_key)
mod.put()
Run Code Online (Sandbox Code Playgroud)

这有可能吗,有人能指出我正确的方向吗?谢谢.

bos*_*ter 5

keys_with_ancestors示例之后,让我们假设我们有相同的导入,并以与在那里定义的MyParent方式相同的方式定义了类.

TL; DR答案基本上是传递parent=给模型构造函数相当于创建一个密钥,其中包含None作为种类ID对列表中的最后一个ID.例如,对于一个类MyModel:

>>> parent = ndb.Key(MyModel, 1)
>>> child = MyModel(parent=parent)
>>> print child.key
ndb.Key('MyModel', 1, 'MyModel', None)
Run Code Online (Sandbox Code Playgroud)

为了对样本执行此操作,我们可以简单地忽略id:

class MyModel(EndpointsModel):
  _parent = None

  attr1 = ndb.StringProperty()
  attr2 = ndb.StringProperty()
  created = ndb.DateTimeProperty(auto_now_add=True)
Run Code Online (Sandbox Code Playgroud)

并且在setter中只需设置半生不熟的密钥,不要尝试从数据存储区中检索(因为密钥不完整):

  def ParentSet(self, value):
    if not isinstance(value, basestring):
      raise TypeError('Parent name must be a string.')

    self._parent = value
    if ndb.Key(MyParent, value).get() is None:
      raise endpoints.NotFoundException('Parent %s does not exist.' % value)
    self.key = ndb.Key(MyParent, self._parent, MyModel, None)

    self._endpoints_query_info.ancestor = ndb.Key(MyParent, value)
Run Code Online (Sandbox Code Playgroud)

类似地,在getter中,您可以直接从键中检索父级(尽管这并不能保证只有一对作为父级):

  @EndpointsAliasProperty(setter=ParentSet, required=True)
  def parent(self):
    if self._parent is None and self.key is not None:
      self._parent = self.key.parent().string_id()
    return self._parent
Run Code Online (Sandbox Code Playgroud)

完成此操作后,您无需更改任何API代码,该示例将按预期工作.