问题:
当我使用 bulkloader 存储数据时,永远不会调用 DecimalProperty.get_value_for_datastore 方法,当我将 5.4 存储在数据存储中时,会完全像这样保存:5.4; 这应该通过 get_value_for_datastore 传递并转换为这样的整数:54000; 因为我需要小数点后4位:5.4 * 10000 = 54000; 然后返回 54000/10000 = 5.4
我有一个模型:
from google.appengine.ext import db
from gae.properties.decimal_property import DecimalProperty
Articles:
price = Decimal(4)
十进制类
from decimal import Decimal
from google.appengine.ext import db
class DecimalProperty(db.Property):
"""
Allows Python's decimal.Decimal type to be stored in the datastore as an
integer. Takes care of putting the decimal point in the right place.
"""
data_type = Decimal
def __init__(self, dec_places, verbose_name=None, name=None, default=None,
required=False, validator=None, choices=None, indexed=True):
super(DecimalProperty, self).__init__(verbose_name, name, default,
required, validator, choices, indexed)
self.__quantize_exp = Decimal('10') ** -dec_places
self.__store_mul = Decimal('10') ** dec_places
def get_value_for_datastore(self, model_inst):
dec = super(DecimalProperty, self).get_value_for_datastore(model_inst)
if dec is None:
return None
dec = dec.quantize(self.__quantize_exp)
return int(dec * self.__store_mul)
def make_value_from_datastore(self, value):
if value is None:
return None
return Decimal(value) / self.__store_mul
def validate(self, value):
if value is not None and not isinstance(value, Decimal):
raise db.BadValueError("Property %s must be a Decimal or string." % self.name)
return super(DecimalProperty, self).validate(value)
def empty(self, value):
return (value is None)
我的散装机是:
from google.appengine.ext import bulkload
from google.appengine.api import datastore_types
import datetime
class ArticleLoader(bulkload.Loader):
def __init__(self):
bulkload.Loader.__init__(self, 'Article', [
('price', str)
])
if __name__ == '__main__':
bulkload.main(ArticleLoader())
我的 csv 文件是这样的:
5.4
笔记:
如果我输入 bulkloader 十进制:
from google.appengine.ext import bulkload
from google.appengine.api import datastore_types
import datetime
from decimal import Decimal
class ArticleLoader(bulkload.Loader):
def __init__(self):
bulkload.Loader.__init__(self, 'Article', [
('price', Decimal)
])
if __name__ == '__main__':
bulkload.main(ArticleLoader())
我收到此错误:
Loading from line 1...error:
Traceback (most recent call last):
File "C:\google_appengine\google\appengine\ext\bulkload\bulkload_deprecated.py", line 306, in LoadEntities
new_entities = loader.CreateEntity(columns, key_name=key_name)
File "C:\google_appengine\google\appengine\ext\bulkload\bulkload_deprecated.py", line 160, in CreateEntity
entity[name] = converter(val)
File "C:\google_appengine\google\appengine\api\datastore.py", line 881, in __setitem__
datastore_types.ValidateProperty(name, value)
File "C:\google_appengine\google\appengine\api\datastore_types.py", line 1477, in ValidateProperty
'Unsupported type for property %s: %s' % (name, v.__class__))
BadValueError: Unsupported type for property price: <class 'decimal.Decimal'>
非常肮脏的解决方案:
('price', to_decimal(4))
def to_decimal(dec_places):
def converter(s):
val = int(round(Decimal(s), dec_places) * 10 ** dec_places)
return val
return converter