在Google云数据存储区中,我的代码与此相同:
req = datastore.CommitRequest()
req.mode = datastore.CommitRequest.NON_TRANSACTIONAL
foo = req.mutation.insert_auto_id.add()
barListProperty = foo.property.add()
barListValue = []
for i in range(5):
ent = datastore.Entity()
a = ent.property.add()
set_property(a, 'a', 1)
b = ent.property.add()
set_property(b, 'b', i)
set_property(barListProperty, 'barlist', barListValue)
key = datastore.Key()
path_element = key.path_element.add()
path_element.kind = 'Foo'
foo.key.CopyFrom(key)
print datastore.commit(req)
现在我想在NDB中构建相同的东西,所以我写了这个:
class Foo(Expando):
pass
foo = Foo()
foo.barlist = [Expando(a=1, b=i) for i in range(5)]
foo.put()
但是我收到以下错误:
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 570, in dispatch
return method(*args, **kwargs)
File "/base/data/home/apps/s~detect-analyze-notify-01a/sjuul.373145649709860280/main.py", line 317, in get
foo.put()
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/model.py", line 3339, in _put
return self._put_async(**ctx_options).get_result()
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py", line 325, in get_result
self.check_success()
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py", line 368, in _help_tasklet_along
value = gen.throw(exc.__class__, exc, tb)
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/context.py", line 748, in put
key = yield self._put_batcher.add(entity, options)
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py", line 368, in _help_tasklet_along
value = gen.throw(exc.__class__, exc, tb)
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/context.py", line 280, in _put_tasklet
keys = yield self._conn.async_put(options, datastore_entities)
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py", line 454, in _on_rpc_completion
result = rpc.get_result()
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/api/apiproxy_stub_map.py", line 612, in get_result
return self.__get_result_hook(self)
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/datastore/datastore_rpc.py", line 1818, in __put_hook
self.check_rpc_success(rpc)
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/datastore/datastore_rpc.py", line 1333, in check_rpc_success
raise _ToDatastoreError(err)
BadRequestError: BLOB, ENITY_PROTO or TEXT properties must be in a raw_property field.
我应该怎么做?
编辑:这不起作用
class Foo(Expando):
pass
class Bar(Expando):
pass
foo = Foo()
foo.barlist=[Bar(a=1, b=i) for i in range(5)]
foo.put()
答案 0 :(得分:1)
您无法直接使用Expando模型。您将需要为重复属性创建一个ndb.Expando的子类,以使其工作。
e.g。
s~lightning-catfish> class X(ndb.Expando):
... pass
s~lightning-catfish> class Repeated(ndb.Expando):
... pass
...
s~lightning-catfish> z = X()
s~lightning-catfish> z.y = [Repeated(a=1,b=i) for i in range(5)]
s~lightning-catfish> z.y
[Repeated(a=1, b=0), Repeated(a=1, b=1), Repeated(a=1, b=2), Repeated(a=1, b=3), Repeated(a=1, b=4)]
答案 1 :(得分:0)
在我看来,你正在尝试保存一个本身尚未保留的实体,这留下了几个选项:
1)如果你想将Entity
存储为一个单独的“行”,你可以保存它,然后存储一个键列表:
class Entity(db.Expando):
pass
# Create your main entity.
e = Entity()
e.other_entities = []
# Create a bunch of others.
for i in range(5):
other_entity = Entity(a=i, b=i+1)
other_entity.put()
# Attach the key to the main entity.
e.other_entities.append(other_entity.key())
# Save your main entity.
e.put()
2)如果您想要Entity
存储“内联”,您可以使用db.EmbeddedEntity
type:
class Entity(db.Expando):
pass
# Create your main entity.
e = Entity()
e.other_entities = []
# Create a bunch of others (but don't save them).
for i in range(5):
other_entity = Entity(a=i, b=i+1)
# Append it to the list as an EmbeddedEntity
e.other_entities.append(db.EmbeddedEntity(other_entity))
# Save your main entity.
e.put()
这样的一个示例是在the main Expando documentation page上,他们使用db.Text('Text value')
来指定它应该存储为TextProperty
而不是StringProperty
。
答案 2 :(得分:0)
一个好的选择是为列表设置一个新实体。因此,您可以根据需要插入任意数量的项目,作为“列表实体”的实例,您可以将其他实体设置为父项。
而不是这个(或类似的):
foo = Foo()
foo.barlist=[Bar(a=1, b=i) for i in range(5)]
foo.put()
你可以试试这个:
foo = ListFoo(parent= Foo)
foo.item = 'list item'
foo.put()