39

I am looking for a way to limit the FloatField in Django to 2 decimal places. Has anyone got a clue of how this could be done without having to use a DecimalField?

I tried decimal_places=2, but this just gave me a migration error within the float field. So, I am thinking this method must only work within DecimalFields.

pmacfarlane
  • 3,057
  • 1
  • 7
  • 24
Aidan Doherty
  • 962
  • 2
  • 11
  • 29
  • 1
    Why don't you want to use a `DecimalField`? – alecxe May 19 '14 at 13:28
  • did u try this `models.FloatField(default=to_some_value)` – ajknzhol May 19 '14 at 13:28
  • because the decimal fields add the increment and decrement arrows within the input box and i dont want that appear i have not tried the default method but will look it up and see if its right for what i need. – Aidan Doherty May 19 '14 at 13:30
  • 1
    @AidanDoherty so, the reason is just how does it appear on the form? You know - you can change it by setting up a different widget for the field. – alecxe May 19 '14 at 13:32
  • @alecxe So i would do that by overwriting the Decimal Field widget to changes its type value then?. – Aidan Doherty May 19 '14 at 13:38
  • You can refer to this link for more info about Django widgets. https://docs.djangoproject.com/en/dev/ref/forms/widgets/ – Rod Xavier May 19 '14 at 13:45

3 Answers3

77

If you are only concerned with how your FloatField appears in forms, you can use the template filter floatformat.

From the Django Docs:

If used with a numeric integer argument, floatformat rounds a number to that many decimal places.

For example, if value = 34.23234, then in your template:

{{ value|floatformat:2 }}  # outputs 34.23
user8193706
  • 2,387
  • 2
  • 8
  • 12
pcoronel
  • 3,833
  • 22
  • 25
  • Thats good but isn't completely what i am looking for but i am sure this will come in handy in the future projects thanks for your help. – Aidan Doherty May 19 '14 at 15:41
  • This helps. I am using Postgres with Django `FloatField(default=0.00)` but its saving it as `0` by removing useless `0s` in decimal places.. which make sense.. but i want to show consistent values `0.00` or `5.43` in template... `{{ value|floatformat:2 }}` did the trick – Lal Jun 21 '17 at 16:07
  • 1
    See my [answer](https://stackoverflow.com/questions/23739030/restrict-django-floatfield-to-2-decimal-places/46081058#46081058) for ensuring that your data field always rounds to two decimals at the database level. – user1847 Sep 07 '17 at 20:54
  • 1
    How to use this with a django ModelForm instance ? – Mohammed Shareef C Feb 08 '21 at 12:13
22

If you'd like to actually ensure that your model always gets saved with only two decimal places, rather than just changing the presentation of the model in a template, a custom save method on your model will work great. The example model below shows how.

class MyDataModel(models.Model):
    my_float = models.FloatField()

    def save(self, *args, **kwargs):
        self.my_float = round(self.my_float, 2)
        super(MyDataModel, self).save(*args, **kwargs)

Now every time you save your model you will guarantee that the field will only be populated with a float of two decimal places. This can be generalized to rounding to any number of decimal places.

user1847
  • 3,571
  • 1
  • 26
  • 35
2

Since Django 1.8+ you can use a custom validator for FloatField/or any ModelFields:

def validate_decimals(value):
    try:
        return round(float(value), 2)
    except:
        raise ValidationError(
            _('%(value)s is not an integer or a float  number'),
            params={'value': value},
        )

...and in your model you can apply it like this:

from django.db import models

class MyModel(models.Model):
    even_field = models.FloatField(validators=[validate_decimals])
Catalin
  • 135
  • 1
  • 7
  • This will not work. Validators do not change the values that are being saved, they only validate that a value is acceptable. If the value is unacceptable an exception should be raised. This will not modify the value that is being saved. – user1847 Sep 06 '17 at 17:15
  • See my answer below for an answer that will ensure a float field rounds to two decimal places. – user1847 Sep 06 '17 at 17:23