Google AppEngine告诉我我的int不是int

0 投票
3 回答
1814 浏览
提问于 2025-04-16 15:43

代码的相关部分:

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 个回答

1

我在删除了一个实体/表中的所有元素后,尝试通过csv/bulkloader上传新值时,也遇到了同样的错误信息。

解决办法是向bulk loader的yaml文件中的属性定义添加以下这一行:

import_transform: transform.none_if_empty(int)

这样就能解决问题了。

2

为你的主键整数属性创建一个自定义验证器。

我觉得@saxon-druce对问题的理解是正确的。

你从数据存储中获取了一个实体,而from_entity函数则是把这个实体的数据应用到你的db.Model的初始化器上。

validate调用来自于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

创建一个简单的验证器,尝试将字符串解析为整数。最终,你可能希望对所有这些实体应用一个映射器,以使它们都符合当前的模式。

验证器在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)

这段代码还没有经过测试。

5

你的模型里有没有一个叫做'pk'的属性?现在它是一个整数类型(IntegerProperty()),但之前是字符串类型(StringProperty())。而且,id为757347的实体是用旧版本的模型保存的?

撰写回答