2013-03-12 4 views
1

Я добавил свойство списка в модель сущности с большим количеством существующих экземпляров.BadValueError: требуется свойство X

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 

Для тех, которые следуют:

По предложению Аарона двойки, изменяя значение по умолчанию для пустого списка решить эту проблему, так:

new_property = db.ListProperty(item_type=str, default=None) 

следует читать:

new_property = db.ListProperty(item_type=str, default=[]) 
+0

Можете ли вы опубликовать еще более подходящий код, например, ваши поисковые вызовы? Похоже, что это может быть слабо связано с http://stackoverflow.com/questions/6142439/badvalueerror-property-xxxx-is-required-even-after-the-xxxx-property-has-alrea?rq=1 –

+0

Этот ответ могут относиться: http://stackoverflow.com/a/10012905/399704 –

+0

В обоих случаях они относятся к атрибуту required = true, применяемому к свойству, но здесь это не так (хотя оно ведет себя как есть, хотя оно и есть) , – notreadbyhumans

ответ

1

Глядя на исходный код Google App Engine в __init__.py ссылка в вашем TRACEBACK, вы можете увидеть комментарий в комментариях ListProperty DOC (строка 3428), который говорит:

Note that the only permissible value for 'required' is True.

Так , даже если вы не снабдив его, это выглядит как линия 3442 устанавливает его автоматически: self._require_parameter(kwds, 'required', True)

Если смотреть дальше в исходный код (строка 3500), вы можете увидеть определение empty() для ListProperty:

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 

я мог думать о двух вопросах, которые могут вызвать ошибку, но я не проверял через тестирование.

1) Если по какой-либо причине у вас уже есть данные в этом поле (возможно, вы повторно используете имя new_property?), И оно было пустым, и, похоже, оно может сгенерировать имеющуюся у вас ошибку. Я не уверен, как исправить эту проблему, за исключением того, что вместо этого вы используете уникальное имя для своего new_property. post I referenced in my comment объясняет, как «исправить» данные.

2) Поскольку у вас уже есть записи, ваш код пытается заполнить те, которые используют значение по умолчанию None, которое соответствует тесту empty(), а затем генерирует исключение. В этом случае, если вы просто укажете значение по умолчанию [], оно должно работать.

+0

См. Мой ответ выше о том, как сгенерировать проблему, а затем, если сущность была написана уже со значением по умолчанию None как StringProperty, тогда изменение значения по умолчанию в [] в определении модели для ListProperty будет по-прежнему совпадать BadValueError, поскольку в этом случае свойство существует и в нем есть None, что является недопустимым значением для ListProperty. –

+0

1) new_property не является свойством или именем свойства, которое использовалось ранее. 2) Изменение значения по умолчанию = Нет по умолчанию = [], похоже, разрешило проблему. – notreadbyhumans

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`, а также выборку записи. Мы получаем ту же трассировку стека. См. Журнал оболочки ниже.

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> 

Для исправления данных вам необходимо будет получить доступ к нему на низком уровне и изменить типы данных, хранящиеся в записи.

У меня есть код для извлечения и размещения объектов без использования моделей, если вы хотите.

* Последнее, что вы должны попробовать *

Попробуйте использовать следующий код или что-то вроде того, чтобы принести объекты без использования модели. Вы возвращаете базовые данные с типами и т. Д. В dicts. Это покажет вам, что находится в хранилище данных.

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]) 
+0

Примером является прямая копия свойства, я не использую его = верно. – notreadbyhumans

+0

Ну что-то происходит, потому что BadValueError: Свойство new_property требуется 'именно то, что вы получаете, когда' required = True' –

+0

ok, None не является допустимым значением по умолчанию для ListProperty, попробуйте изменить значение по умолчанию на '[]' –

Смежные вопросы