Django antipatterns 〉antipattern 〉Using a FloatField for money Fork me on GitHub

Often for quantities that require precise calculations, a FloatField [Django-doc] is used. This is not a good idea since decimal numbers often can not be precisely converted to a float, so it will result in rounding errors. These errors will further propagate when one performs calculations.

Why is it a problem?

A float uses the IEEE-754 standard [wiki] to represent floating point numbers. While this is a good standard and actually aims to make calculations very precise, it can result in rounding errors for decimal numbers. Quantities like currencies make use of the decimal number system, and often do not allow much rounding errors.

What can be done to resolve the problem?

One can make use of a DecimalField [Django-doc]. DecimalFields are represented at the Django/Python layer as a Decimal, and at the database often use a dedicated decimal type. These represent numbers as decimal numbers, and thus make, for decimal numbers, correct sums, etc.

from django.db import models

class Product(models.Model):
    price = models.DecimalField(max_digits=12, decimal_places=2)

The Django documentation has a section on FloatField vs. DecimalField which compares both types.

Extra tips

There are Django packages that make it more convenient to work with money. For example django-money [GitHub] and django-moneyfield [GitHub].

These represent money with two fields, a DecimalField for the value, and an extra column that denotes the currency. This is often more convenient and provides extra functionalities like converting money from one currency to another.