Select Page

At some point in doing web application using web2py/Python I need to show numbers in money formatted string. Seems a little problem easy to handle, at first. After searching about money at Python Package Index then I know it was quite complex matter involved many things… Anyway, the money format for my purpose it is enough to use simple function to convert number to money formatted string, and I use “moneyfmt” recipe I found at Python Docs, modified it a little, set places=0  as default, add condition if places == 0  to automatically set dp=”  if places=0, so I don’t have to set “dp” parameter when I need to change the number of “places”.

def moneyfmt(value, places=0, curr='', sep=',', dp='.', pos='', neg='(', trailneg=''):
    """Convert Decimal to a money formatted string.

    places:  required number of places after the decimal point
    curr:    optional currency symbol before the sign (may be blank)
    sep:     optional grouping separator (comma, period, space, or blank)
    dp:      decimal point indicator (comma or period)
             only specify as blank when places is zero
    pos:     optional sign for positive numbers: '+', space or blank
    neg:     optional sign for negative numbers: '-', '(', space or blank
    trailneg:optional trailing minus indicator:  '-', ')', space or blank

    >>> d = Decimal('-1234567.8901')
    >>> moneyfmt(d, curr='$')
    '-$1,234,567.89'
    >>> moneyfmt(d, places=0, sep='.', dp='', neg='', trailneg='-')
    '1.234.568-'
    >>> moneyfmt(d, curr='$', neg='(', trailneg=')')
    '($1,234,567.89)'
    >>> moneyfmt(Decimal(123456789), sep=' ')
    '123 456 789.00'
    >>> moneyfmt(Decimal('-0.02'), neg='<', trailneg='>')
    '<0.02>'

    """
    q = Decimal(10) ** -places      # 2 places --> '0.01'
    sign, digits, exp = value.quantize(q).as_tuple()
    result = []
    digits = map(str, digits)
    build, next = result.append, digits.pop

    if places == 0:
        dp = ''

    if sign:
        build(trailneg)
    for i in range(places):
        build(next() if digits else '0')

    build(dp)
    if not digits:
        build('0')

    i = 0
    while digits:
        build(next())
        i += 1
        if i == 3 and digits:
            i = 0
            build(sep)
    build(curr)
    build(neg if sign else pos)
    return ''.join(reversed(result))

Then, for example, I put this function in models/db.py , don’t forget to import Decimal:

from decimal import Decimal
def moneyfmt(value, places=0, curr='', sep=',', dp='.', pos='', neg='(', trailneg=''):

...
...

and we can use it application-wide, for example in views/default/showbill.html, like:

<table class='table'>
  <tr><td width="30%">{{=T('Bill No')}}</td><td>: {{=bill.bill_no}}</td></tr>
  <tr><td>{{=T('Total bill')}}</td><td>: {{=moneyfmt(bill.total)}}</td></tr>
  <tr><td></td><td></td></tr>
</table>

 

Trackbacks/Pingbacks

  1. Money-formatted numbers in SQLFORM grid | Cuma Bilang - […] use function moneyfmt() posted here to format the numbers, shown in grid […]

Submit a Comment

Your email address will not be published. Required fields are marked *