使用GAE + WTForms处理价格数字

时间:2011-12-12 03:19:53

标签: python google-app-engine internationalization jinja2 money-format

我使用Google应用引擎(python)和Jinja2,我想利用webapp2的功能进行货币国际化和本地化,即将商品价格作为数字,并使用webapp2的内置i18n方法进行正确的格式化。然后首先我必须有我的价格的正确数据类型。

我正在从使用String for price的原型迁移到更实际的实现,其中我使用一些数字数据类型作为价格+另一个变量是哪种货币。所以在迁移的同时我将使用两个变量,使用数字转换为字符串,删除字符串数据类型并生成mapreduce作业以将旧实体更新为基于数字的变量,如整数或小数,而不是允许text /表示价格的字符串。

我的环境(谷歌应用引擎)不支持十进制数据类型,我也可能只使用整数,因为使用是购买和销售更多的exapensive文章和物品,如房屋,汽车等,美元很重要,美分通常只列为00.所以我放弃了实现小数属性的项目,无论如何它都是bugging,现在我问哪个是设置价格的正确方法,如果我必须在它保存之前进行转换?

IE中。这是对的:

form = EntityForm(self.request.params)
if form.validate():
    entity.title = form.title.data
    entity.name = form.name.data
    entity.email = form.email.data
    entity.text = form.text.data
    entity.set_password(form.password.data)
    entity.price = form.price.data
    try:
      if form.price.data:
        form.price.data=form.price.data.replace(',','.').replace(' ', '')
        entity.integer_price = int(form.price.data)
    except:
      pass

或者我不必将变量转换为整数,并且将在幕后处理类型转换?我相信表单变量是字符串,价格必须是一个数字才能正确排序和过滤。

当我使用自定义的十进制属性时,我开始收到此错误:

Traceback (most recent call last):
  File "/base/python27_runtime/python27_lib/versions/third_party/webapp2-2.3/webapp2.py", line 545, in dispatch
    return method(*args, **kwargs)
  File "/base/data/home/apps/s~montaoproject/validation.355292363398040911/i18n.py", line 653, in get
    ads = paginator.page(page)
  File "/base/data/home/apps/s~montaoproject/validation.355292363398040911/paginator.py", line 42, in page
    return Page(self.object_list[bottom:top], number, self)
  File "/base/python27_runtime/python27_lib/versions/1/google/appengine/ext/db/__init__.py", line 2189, in __getitem__
    return self.fetch(limit, start)
  File "/base/python27_runtime/python27_lib/versions/1/google/appengine/ext/db/__init__.py", line 2084, in fetch
    return list(self.run(limit=limit, offset=offset, **kwargs))
  File "/base/python27_runtime/python27_lib/versions/1/google/appengine/ext/db/__init__.py", line 2237, in next
    return self.__model_class.from_entity(self.__iterator.next())
  File "/base/python27_runtime/python27_lib/versions/1/google/appengine/ext/search/__init__.py", line 463, in from_entity
    return super(SearchableModel, cls).from_entity(entity)
  File "/base/python27_runtime/python27_lib/versions/1/google/appengine/ext/db/__init__.py", line 1411, in from_entity
    entity_values = cls._load_entity_values(entity)
  File "/base/python27_runtime/python27_lib/versions/1/google/appengine/ext/db/__init__.py", line 1387, in _load_entity_values
    value = prop.make_value_from_datastore(entity[prop.name])
  File "/base/data/home/apps/s~montaoproject/validation.355292363398040911/main.py", line 98, in make_value_from_datastore
    return decimal.Decimal(value)
  File "/base/python27_runtime/python27_dist/lib/python2.7/decimal.py", line 548, in __new__
    "Invalid literal for Decimal: %r" % value)
  File "/base/python27_runtime/python27_dist/lib/python2.7/decimal.py", line 3844, in _raise_error
    raise error(explanation)
InvalidOperation: Invalid literal for Decimal: u''

我使用的代码是:

class DecimalProperty(db.Property):
  data_type = decimal.Decimal

  def get_value_for_datastore(self, model_instance):
    return str(super(DecimalProperty, self).get_value_for_datastore(model_instance))

  def make_value_from_datastore(self, value):
    return decimal.Decimal(value)

  def validate(self, value):
    value = super(DecimalProperty, self).validate(value)
    if value is None or isinstance(value, decimal.Decimal):
      return value
    elif isinstance(value, basestring):
      return decimal.Decimal(value)
    raise db.BadValueError("Property %s must be a Decimal or string." % self.name)

但这对我不起作用,我开始将“无”这个词作为文章/对象的字符串,没有定价使我的应用程序无法正确加载所以我完全删除了十进制尝试,我要去对于具有integerproperty的解决方案而且验证该输入是空的还是我可以用wtforms执行的整数。

所以我不再使用自定义小数,我们决定integerproperty会这样做,最坏的情况是如果需要一个货币的分数那么可以使用另一个变量“美分”,这样我就可以使用整数来计算美元和整数后者很少或从未使用过。

所以我现在正在计划的解决方案很简单:

class Article(GeoModel,search.SearchableModel):

integer_price = IntegerProperty() #store dollars as dollars
currency = db.StringProperty(choices=(
    'EUR',
    'ARS',
    'AUD',
    'BRL',
    'GBP',
    'CAD',
    'CZK',
    'DKK',
    'HKD',
    'HUF',
    'ILS',
    'INR',
    'JPY',
    'MXN',
    'NZD',
    'NOK',
    'PLN',
    'PHP',
    'SGD',
    'SEK',
    'SGD',
    'CHF',
    'USD',
    'THB',
    'TWB',
    ), verbose_name='Currency')
price = db.StringProperty(verbose_name='price')  #quit using this and use a number instead

你知道我是否真的必须进行类型转换或任何其他我可能陷入的陷阱?你是否同意我的用例(广告汽车,广告房屋)等我不需要小数,尽管我可以想象一下我必须禁止的更具异国情调的价格。 “每加仑20美元”是我无法处理的价格,但它可以在文中指定,因为它是一种特殊类型的价格(每单位体积),同样如果价格是美分。将价格存储为integerproperty可以更好地格式化价格,特别是因为我的应用程序是国际化和本地化的。

感谢您的回答或评论

1 个答案:

答案 0 :(得分:1)

请查看问题编号6595以及this。如果你的问题出在这个区域,它可以通过补丁解决,我建议捕获一个except块中的区域并转储变量esp个别序号以确保传递给Decimal的是一个合法的可接受字符。对我而言,它抱怨的角色是一个空字符串看起来有点奇怪,所以让我们尝试确认所有角色都是有效的,因为我们在这里处理unicode。