我已将list属性添加到具有大量现有实例的实体模型中。
class MyModel(db.Model):
new_property = db.ListProperty(item_type=str, default=None)
部署到实时环境后,应用程序会在短时间内无问题地运行,然后在尝试从数据存储中检索记录时开始抛出BadValueError错误。
抛出错误的代码只是对数据存储区的直接调用:
app_item = db.get(app_item_key)
我使用的是1.7.5。 Python 2.7运行时。
我可以采取哪些措施来防止这种情况发生,或者至少陷入困境,以便我可以从商店获取数据?
Traceback (most recent call last):
File "/base/data/home/apps/app/4-15.365909351579418812/app.py", line 1739, in app_get
app_item = db.get(app_item_key)
File "/python27_runtime/python27_lib/versions/1/google/appengine/ext/db/__init__.py", line 1533, in get
return get_async(keys, **kwargs).get_result()
File "/python27_runtime/python27_lib/versions/1/google/appengine/api/apiproxy_stub_map.py", line 604, in get_result
return self.__get_result_hook(self)
File "/python27_runtime/python27_lib/versions/1/google/appengine/datastore/datastore_rpc.py", line 1459, in __get_hook
entities = rpc.user_data(entities)
File "/python27_runtime/python27_lib/versions/1/google/appengine/api/datastore.py", line 600, in local_extra_hook
return extra_hook(result)
File "/python27_runtime/python27_lib/versions/1/google/appengine/ext/db/__init__.py", line 1503, in extra_hook
model = cls1.from_entity(entity)
File "/python27_runtime/python27_lib/versions/1/google/appengine/ext/db/__init__.py", line 1438, in from_entity
return cls(None, _from_entity=entity, **entity_values)
File "/python27_runtime/python27_lib/versions/1/google/appengine/ext/db/__init__.py", line 970, in __init__
prop.__set__(self, value)
File "/python27_runtime/python27_lib/versions/1/google/appengine/ext/db/__init__.py", line 614, in __set__
value = self.validate(value)
File "/python27_runtime/python27_lib/versions/1/google/appengine/ext/db/__init__.py", line 3460, in validate
value = super(ListProperty, self).validate(value)
File "/python27_runtime/python27_lib/versions/1/google/appengine/ext/db/__init__.py", line 641, in validate
raise BadValueError('Property %s is required' % self.name)
BadValueError: Property new_property is required
对于以下人员:
根据Aaron D的建议,将默认值更改为空列表可解决此问题,因此:
new_property = db.ListProperty(item_type=str, default=None)
应阅读:
new_property = db.ListProperty(item_type=str, default=[])
答案 0 :(得分:1)
在回溯中引用的__init__.py
中查看Google App Engine的源代码,您可以在ListProperty文档评论(第3428行)中看到评论:
请注意,'required'唯一允许的值为True。
所以,即使你没有提供它,它看起来像3442行自动设置它:
self._require_parameter(kwds, 'required', True)
如果您仔细查看源代码(第3500行),您可以看到empty()
的{{1}}定义:
ListProperty
我可以想到两个可能导致错误的问题,但我没有通过测试验证。
1)如果由于某种原因,你已经在该字段中有数据(也许你正在重用def empty(self, value):
"""Is list property empty.
[] is not an empty value.
Returns:
True if value is None, else false.
"""
return value is None
名称?)并且它是空的,那么它似乎可能会产生你的错误。我不知道如何解决此问题,除了建议您使用new_property
的唯一名称。 post I referenced in my comment解释了如何“修复”数据。
2)由于您已有记录,因此您的代码正在尝试使用与new_property
测试匹配的默认值None
填充那些记录,然后抛出异常。在这种情况下,如果您只是提供默认值empty()
,它应该可以正常工作。
答案 1 :(得分:0)
我很确定你的示例代码不是你正在使用的。我打赌你在新房产里有required=True
。然后,您正在检索没有所需属性值的旧记录。只需删除' required = True`就会使这些错误消失。如果需要具有所需的值,则需要在强制执行约束之前将默认值添加到字段中。
*删除了一些关于None
不是ListProperty的有效默认值的完整垃圾
所以我尝试根据您提供的信息复制情况
我有答案我可以通过首先创建一个名为new_property
的StringProperty类型的模型来生成问题,默认值为None。 put()记录没有new_property getting the default of None written, then change the model definition of new_property to
ListProperty`的值,并获取记录。我们得到相同的堆栈跟踪。请参阅下面的shell日志。
s~lightning-catfish> class MyModel(db.Model):
... pass
...
s~lightning-catfish> x = MyModel()
s~lightning-catfish> x.put()
datastore_types.Key.from_path(u'MyModel', 1001L, _app=u's~lightning-catfish')
s~lightning-catfish> class MyModel(db.Model):
... new_property = db.ListProperty(item_type=str,default=None)
...
s~lightning-catfish> y = db.get(x.key())
s~lightning-catfish> y
<MyModel object at 0x9e09dcc>
s~lightning-catfish> y.new_property
[]
s~lightning-catfish> new_property = db.StringProperty(defaul
KeyboardInterrupt
s~lightning-catfish> class MyModel(db.Model):
... new_property = db.StringProperty(default=None)
...
s~lightning-catfish> z = MyModel()
s~lightning-catfish> z.put()
datastore_types.Key.from_path(u'MyModel', 2001L, _app=u's~lightning-catfish')
s~lightning-catfish> class MyModel(db.Model):
... new_property = db.ListProperty(item_type=str,default=None)
...
s~lightning-catfish> a1 = db.get(z.key())
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/home/timh/google_appengine/google/appengine/ext/db/__init__.py", line 1533, in get
return get_async(keys, **kwargs).get_result()
File "/home/timh/google_appengine/google/appengine/api/apiproxy_stub_map.py", line 604, in get_result
return self.__get_result_hook(self)
File "/home/timh/google_appengine/google/appengine/datastore/datastore_rpc.py", line 1459, in __get_hook
entities = rpc.user_data(entities)
File "/home/timh/google_appengine/google/appengine/api/datastore.py", line 600, in local_extra_hook
return extra_hook(result)
File "/home/timh/google_appengine/google/appengine/ext/db/__init__.py", line 1503, in extra_hook
model = cls1.from_entity(entity)
File "/home/timh/google_appengine/google/appengine/ext/db/__init__.py", line 1438, in from_entity
return cls(None, _from_entity=entity, **entity_values)
File "/home/timh/google_appengine/google/appengine/ext/db/__init__.py", line 970, in __init__
prop.__set__(self, value)
File "/home/timh/google_appengine/google/appengine/ext/db/__init__.py", line 614, in __set__
value = self.validate(value)
File "/home/timh/google_appengine/google/appengine/ext/db/__init__.py", line 3460, in validate
value = super(ListProperty, self).validate(value)
File "/home/timh/google_appengine/google/appengine/ext/db/__init__.py", line 641, in validate
raise BadValueError('Property %s is required' % self.name)
BadValueError: Property new_property is required
s~lightning-catfish>
要修复数据,您需要以较低级别访问它,并更改记录中存储的数据类型。
如果你需要,我有代码可以在不使用模型的情况下获取和放置实体。
*最后你应该尝试*
尝试使用以下代码或类似代码来获取对象而不使用模型。 你可以获得基础数据,类型等等。这将显示数据存储区中的内容。
from google.appengine.api import datastore
from google.appengine.api import datastore_errors
def get_entities(keys):
rpc = datastore.GetRpcFromKwargs({})
keys, multiple = datastore.NormalizeAndTypeCheckKeys(keys)
entities = None
try:
entities = datastore.Get(keys, rpc=rpc)
except datastore_errors.EntityNotFoundError:
assert not multiple
return entities
x = get_entities([some_key])