BadValueError:属性X是必需的

时间:2013-03-12 21:10:24

标签: python google-app-engine

我已将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=[])

2 个答案:

答案 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])