Google AppEngine сообщает мне, что мой int не является int - PullRequest
0 голосов
/ 14 апреля 2011

Соответствующая часть кода:

pk = int(pk)                              
logging.info('pk: %r :: %s', pk, type(pk))
instance = models.Model.get_by_id(int(pk))       

Вывод из сообщения журнала выше

pk: 757347 :: <type 'int'>

Трассировка стека:

Traceback (most recent call last):
  File "/base/python_runtime/python_lib/versions/1/google/appengine/ext/webapp/__init__.py", line 634, in __call__
    handler.get(*groups)
  File "/base/data/home/apps/<myapp>/<version>/scrape.py", line 61, in get
    instance = models.Model.get_by_id(int(pk))
  File "/base/python_runtime/python_lib/versions/1/google/appengine/ext/db/__init__.py", line 1212, in get_by_id
    return get(keys[0], config=config)
  File "/base/python_runtime/python_lib/versions/1/google/appengine/ext/db/__init__.py", line 1434, in get
    model = cls1.from_entity(entity)
  File "/base/python_runtime/python_lib/versions/1/google/appengine/ext/db/__init__.py", line 1350, in from_entity
    instance = cls(None, _from_entity=True, **entity_values)
  File "/base/python_runtime/python_lib/versions/1/google/appengine/ext/db/__init__.py", line 890, in __init__
    prop.__set__(self, value)
  File "/base/python_runtime/python_lib/versions/1/google/appengine/ext/db/__init__.py", line 593, in __set__
    value = self.validate(value)
  File "/base/python_runtime/python_lib/versions/1/google/appengine/ext/db/__init__.py", line 2967, in validate
    % (self.name, type(value).__name__))
BadValueError: Property pk must be an int or long, not a unicode

У кого-нибудь есть идея, если я здесь что-то не так делаю?

Примечание: удаление int из последней строки кода не имеет значения (это была первая версия).

Кроме того, код работает без проблем на dev_appserver.py.

Ответы [ 3 ]

5 голосов
/ 14 апреля 2011

Имеет ли ваша модель свойство 'pk', которое теперь является IntegerProperty (), но ранее было StringProperty (), а объект с идентификатором 757347 был сохранен со старой версией модели?

2 голосов
/ 14 апреля 2011

Создайте пользовательский валидатор для вашего pk IntegerProperty.

Я думаю, @ saxon-druce имеет правильное представление о том, что не работает.

Вы получаете сущность из хранилища данных и функцию from_entity.это применить данные от сущности к инициализатору для вашей модели db.Model.

Подтвердить вызов из google/appengine/ext/db/__init__.py

из SDK

class IntegerProperty(Property):
  """An integer property."""

  def validate(self, value):
    """Validate integer property.

    Returns:
      A valid value.

    Raises:
      BadValueError if value is not an integer or long instance.
    """
    value = super(IntegerProperty, self).validate(value)
    if value is None:
      return value





    if not isinstance(value, (int, long)) or isinstance(value, bool):
      raise BadValueError('Property %s must be an int or long, not a %s'
                          % (self.name, type(value).__name__))
    if value < -0x8000000000000000 or value > 0x7fffffffffffffff:
      raise BadValueError('Property %s must fit in 64 bits' % self.name)
    return value

  data_type = int

Создайте свой собственный тривиальный валидатор, который пытается проанализировать строку как int.В конце концов, вы, вероятно, захотите применить маппер ко всем этим сущностям, чтобы привести их все к текущей схеме.

Валидатор вызывается внутри value = super(IntegerProperty, self).validate(value), поэтому значение должно быть готово для использования в качестве целого всоответствующее время.

Пример валидатора

def str_int_validator(value):
    if isinstance(value, basestring):
        if value.isdigit():
            return int(value)
        else:
            raise db.BadValueError("Property expected str or int got %r" % value)
    else:
        return value

class Foo(db.Model):

    pk = db.IntegerProperty(validator=str_int_validator)

Этот код не был проверен.

1 голос
/ 18 июля 2011

У меня было то же сообщение об ошибке после удаления всех элементов в одной сущности / таблице и последующей попытки загрузить новые значения через csv / bulkloader.

Решением было добавить следующую строку

import_transform: transform.none_if_empty(int)

к определению свойства в файле yaml для массового загрузчика.

...