获取Python NDB时出现重复整数属性的错误
我有一个应用引擎的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
如果我把那个属性从模型定义中去掉,它就能正常返回,所以我知道是这个属性出了问题。在数据存储中,这个字段的值显示为null。你知道这是为什么吗?该怎么解决呢?谢谢!
1 个回答
2
这种情况通常发生在你最开始有一个单一的、没有重复的属性,然后把它改成一个可以重复的属性。当你第一次使用 put()
方法时,如果你还没有设置这个属性,它的值会被填充为 None。但是,如果你之后把它改成了一个可以重复的属性,ndb 会读取这个信息,认为你想要的是 [None]
。因为 None
不是一个有效的整数属性,所以在尝试序列化并使用 put()
存储数据时就会失败。
在你的例子中,它在执行 get()
时失败,因为从数据存储中获取数据后,它尝试序列化这些数据并把它放入内存缓存中。
根据你的情况,你有几个选择:
- 如果你只是在开发服务器上运行,可以通过执行
devappserver.py --clear_datastore
来清空你的数据存储。 搜索所有值为 None 的对象,并把它们替换为空列表。这个过程可能看起来像这样:
for c in Car.query(Car.tags=None): c.tags=[] c.put()
注意,这里有几个地方需要小心。首先,确保 c.tags 只有 [None],而不是 [a, b, c, None],以防万一。其次,如果你有很多没有标签的汽车,你可能无法在同一个请求中处理所有这些。你可能需要在后台运行,或者把数据传递给任务进行处理。
这和第二个选项很相似,但如果你的数据量很小,你可以使用数据存储查看器,简单地把实体的标签重新保存为 None。