Обработка чисел, которые являются ценами с GAE + WTForms - PullRequest
0 голосов
/ 12 декабря 2011

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

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

Моя среда (механизм приложений 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» в виде строки для статей / объектов, которые не имели цены, из-за которой мое приложение не загружалось должным образом, поэтому я полностью удалил попытку десятичной дроби, и я собираюсь для решения с целочисленным свойством вместо этого и подтвердите, что входные данные либо пустые, либо целое число, которое я могу сделать с помощью 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 Ответ

1 голос
/ 12 декабря 2011

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

...