Google AppEngine tells me that my int is not an int
The relevant part of the code:
pk = int(pk)
logging.info('pk: %r :: %s', pk, type(pk))
instance = models.Model.get_by_id(int(pk))
The output from the log message above
pk: 757347 :: <type 'int'>
The stacktrace:
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", li开发者_StackOverflow中文版ne 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
Anyone has an idea if I'm doing something wrong here?
Note: removing the int
from the last line of the code makes no difference (that was the first version).
Also, the code works without a problem on dev_appserver.py
.
Does your model have a property 'pk', which is now an IntegerProperty(), but was previously a StringProperty(), and the entity with id 757347 was saved with the old version of the model?
Create a custom validator for your pk IntegerProperty.
I think @saxon-druce has the right idea about what is failing.
You are receiving an entity from datastore and the from_entity function is apply the data from the entity to an initializer for your db.Model.
validate call is from google/appengine/ext/db/__init__.py
From 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
Create your own trivial validator that attempts to parse an string as an int. Eventually you would probably want to apply a mapper across all of these entities to bring them all up to the current schema.
The validator is called inside value = super(IntegerProperty, self).validate(value)
so the value should be ready to use as an int at the appropriate time.
Example Validator
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)
This code hasn't been tested.
I had the same error message after deleting all elements in one entity/table and then trying to upload new values via csv/bulkloader.
The solution was to add the following line
import_transform: transform.none_if_empty(int)
to the property definition in the yaml file for the bulk loader.
精彩评论