Обработка чисел, которые являются ценами с GAE + WTForms

Я использую Google App Engine (Python) и Jinja2, и я хотел бы воспользоваться преимуществами функции webapp2 для интернационализации и локализации валюты, то есть хранить цены в виде числа и делать правильное форматирование, используя встроенный метод webapp2 i18n. Тогда сначала у меня должен быть правильный тип данных для моих цен.

Я перехожу от прототипа, который использовал String для цен, к более реальной реализации, где я использую некоторый числовой тип данных для цен + другую переменную, в какой валюте это происходит. Таким образом, в то же время в процессе миграции я буду использовать обе переменные, перейти к использованию чисел вместо строк, удалить тип данных string и выполнить задание mapreduce, чтобы обновить старые сущности до числовой переменной, такой как integer или decimal, вместо того, чтобы разрешать текст / строка для представления цены.

Моя среда (движок приложений Google) не поддерживает десятичный тип данных, и я мог бы также использовать только целые числа, так как он используется для покупки и продажи более излишних статей и объектов, таких как дома, автомобили и т. Д., Где доллары имеют значение и обычно центы указан только как 00. Таким образом, я отбросил проект реализации десятичного свойства, и он все равно глючил, и теперь я спрашиваю, какой правильный способ установить цену, и должен ли я привести ее до сохранения?

То есть. это правильно:

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)

Но это не сработало для меня, я начал получать слово "None" в виде строки для статей / объектов, которые не имели цены, из-за которой мое приложение не загружалось должным образом, поэтому я полностью удалил попытку десятичной дроби, и я иду к решению вместо integerproperty и подтвердите, что входные данные либо пустые, либо целое число, которое я могу сделать с помощью wtforms.

Поэтому я больше не использую пользовательское десятичное число, и мы решили, что integerproperty подойдет, и в худшем случае, если понадобится дробная часть валюты, можно использовать другую переменную "центы", чтобы я использовал целые числа для долларов и целые числа для центов, а последний редко или никогда не используется.

Поэтому решение, которое я планирую сейчас, простое:

Статья класса (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 долларов за галлон" - это цена, с которой я не могу справиться, но вместо этого ее можно указать в тексте, поскольку это особый тип цены (за единицу объема), а также, если цена указана в центах. Хранение цены как целочисленного свойства позволит значительно улучшить форматирование цен, тем более что мое приложение интернационализировано и локализовано.

Спасибо за любой ответ или комментарий

1 ответ

Решение

Пожалуйста, посмотрите на номер 6595, а также это. Если ваша проблема лежит в этой области, то она может быть решена патчем, иначе я бы предложил захватить область в блоке исключений и вывести переменную esp индивидуального порядкового номера, чтобы убедиться, что то, что передается в десятичную, является допустимым допустимым символом, Мне кажется немного странным, что символ, на который он жалуется, - пустая строка, поэтому давайте попробуем подтвердить, что все символы действительны, так как мы имеем дело с юникодом здесь.

Другие вопросы по тегам