【问题标题】:Error when fetch Python NDB with repeated integer property获取具有重复整数属性的 Python NDB 时出错
【发布时间】:2014-03-31 18:18:24
【问题描述】:

我有一个应用引擎 Python NDB 模型,如下所示:

class Car(ndb.Model)
name=ndb.StringProperty()
tags=ndb.IntegerProperty(repeated=True)

当我去取车时,我会使用:

car = ndb.Key('Car', long(6079586488025088)).get()

当我这样做时,我看到:

 File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/key.py", line 532, in get
    return self.get_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 371, in _help_tasklet_along
    value = gen.send(val)
  File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/context.py", line 689, in get
    pbs = entity._to_pb(set_key=False).SerializePartialToString()
  File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/model.py", line 3052, in _to_pb
    prop._serialize(self, pb, projection=self._projection)
  File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/model.py", line 1365, in _serialize
    values = self._get_base_value_unwrapped_as_list(entity)
  File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/model.py", line 1135, in _get_base_value_unwrapped_as_list
    wrapped = self._get_base_value(entity)
  File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/model.py", line 1123, in _get_base_value
    return self._apply_to_values(entity, self._opt_call_to_base_type)
  File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/model.py", line 1295, in _apply_to_values
    value[:] = map(function, value)
  File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/model.py", line 1177, in _opt_call_to_base_type
    value = _BaseValue(self._call_to_base_type(value))
  File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/model.py", line 1198, in _call_to_base_type
    return call(value)
  File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/model.py", line 1274, in call
    newvalue = method(self, value)
  File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/model.py", line 1536, in _validate
    (value,))
BadValueError: Expected integer, got None

如果我从模型定义中删除该属性,它会返回正常,所以我知道它就是这个属性。在数据存储中,它被列为该字段具有空值。知道为什么会发生这种情况以及如何处理吗?谢谢!

【问题讨论】:

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


    【解决方案1】:

    这通常发生在您首先拥有单个非重复属性,然后将其转换为重复属性时。当您最初执行put() 时,如果您尚未设置属性,它将用 None 填充该值。然而,如果你把它变成一个重复的属性,ndb 会读到这个并认为你想要[None]。因为None 不是有效的IntegerProperty,尝试序列化和put() 数据将失败。

    在您的示例中,它在 get() 上失败,因为在从数据存储区执行 get() 之后,它会尝试序列化数据并将其放入内存缓存中。

    根据您的情况,您有两种选择:

    1. 如果您只在 devappserver 中运行,请通过运行 devappserver.py --clear_datastore 清除您的数据存储区
    2. 搜索所有具有 None 值的对象并将它们替换为空列表。这可能看起来像这样:

      对于 Car.query 中的 c(Car.tags=None): c.tags=[] c.put()

      请注意,您必须注意这里的一些事情。首先,确保 c.tags only 是 [None] 而不是 [a, b, c, None],以防万一。其次,如果你有很多没有标签的汽车,你将无法在同一个请求中修复它们。您要么希望在后端运行,要么将数据传递给 Tasks 进行处理。

    3. 这与 #2 非常相似,但如果您的数据非常少,您可以使用 Datastore 查看器并简单地使用 tags = None 重新保存实体。

    【讨论】:

    • 我选择选项 2,我认为它无法处理“无”很奇怪。我遇到的一个怪癖是尝试测试我想通过密钥获取的这个,但发现这当然让我陷入了原始错误,但是通过密钥以外的其他东西查询并没有导致同样的问题,我能够测试单个条目。不知道为什么通过 Key 获取会导致问题,但查询并没有给出两者都返回相同的对象。
    • 问题在于 get 与查询不同,它尝试将实体保存到内存缓存。此时 ndb 尝试序列化实体并失败。您可以通过关闭 memcache 来解决此问题,直到通过调用 ndb.get_context().set_memcache_policy(False) 解决问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-12
    • 2013-04-05
    • 1970-01-01
    • 2013-01-21
    • 2015-09-08
    • 1970-01-01
    相关资源
    最近更新 更多