Currency Fields with newforms

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import re
from django import newforms as forms

class CurrencyField (forms.RegexField):
    currencyRe = re.compile(r'^[0-9]{1,5}(.[0-9][0-9])?$')
    def __init__(self, *args, **kwargs):
        super(CurrencyField, self).__init__(
            self.currencyRe, None, None, *args, **kwargs)

    def clean(self, value):
        value = super(CurrencyField, self).clean(value)
        return float(value)

class CurrencyInput (forms.TextInput):
    def render(self, name, value, attrs=None):
        if value != '':
            try:
                value = u"%.2f" % value
            except TypeError:
                pass
        return super(CurrencyInput, self).render(name, value, attrs)

class MyForm (forms.Form):
    amount = CurrencyField(widget=CurrencyInput, initial=5)

More like this

  1. Newforms field for decimals with a comma by jonasvp 6 years, 1 month ago
  2. Currency Field Admin Integration by Rupe 4 years, 10 months ago
  3. Currency DB Field by Rupe 4 years, 10 months ago
  4. Currency Widget by Rupe 4 years, 10 months ago
  5. Automatically trim newforms text fields by miracle2k 6 years, 6 months ago

Comments

afternoon (on April 13, 2007):

Looks good, but is Decimal a better choice than float?

#

sago (on April 17, 2007):

Yes you could replace line 12 with

return decimal.Decimal(value)

but to take advantage of that extra accuracy, you'd need to use IntegerField in the database and do fixed-point conversion when you read and write it.

As it stands above (assuming a FloatField database column) the Decimal will buy you nothing, as the value is returned via float() by django, so you'll run out of accuracy at the same point.

As a general rule, however, it is better to use Decimal than float in python when dealing with currency.

#

Dyadya Zed (on April 18, 2007):

May be it would better to use NumPy (it is scientific python extension for very long integer numbers and operations between them)

#

akaihola (on January 10, 2008):

You could reverse the order in which CurrencyField and CurrencyInput are defined, and add

widget = CurrencyInput

to the definition of CurrencyField.

This way there's no need to define the form field's widget class explicitly.

#

akaihola (on January 10, 2008):

Easy internationalization: to handle both dot and comma as a decimal separator, use this regex:

currencyRe = re.compile(r'^[0-9]{1,5}([,\.][0-9][0-9])?$')

Replace CurrencyField's clean() return value with

return float(value.replace(',', '.'))

If you want to display commas instead of dots in forms by default, replace CurrencyInput's try clause with

value = (u"%.2f" % value).replace('.', ',')

#

zejn (on April 4, 2011):

You really really really should't use float for monetary values. In some cases it's even illegal, because float loses precision and with money that's a no-no.

#

(Forgotten your password?)