6

So I never would have used Django's DecimalField option if I had known how difficult it would be to serialize my model data into JSON as a result.

Long story short, how do I get the float value from a DecimalField?

My model looks like this:

class DailyReport(models.Model):
    earnings = models.DecimalField(max_digits=12, decimal_places=4)

    def earnings_float(self):
        return self.earnings.to_float()

Obviously there is no to_float() method available, so what do I do instead?

BELOW IS LATER ADDITION:

This works:

class DailyReport(models.Model):
    earnings = models.DecimalField(max_digits=12, decimal_places=4)

    def earnings_float(self):
        return float(self.earnings)

But even this seems too complicated. I'm trying to use django-rest-framework for all the serializing, since I'm using it for rest-framework stuff in my app generally. In this particular case I'd just like to transform and serialize my data into python lists and dictionaries and then store them as documents in Mongo DB via pymongo 3.

tadasajon
  • 14,276
  • 29
  • 92
  • 144

4 Answers4

8

Just cast the DecimalField to a float:

def earnings_float(self):
        return float(self.earnings)
Jeff K
  • 96
  • 4
  • Beware that a `DecimalField` can be None and `float()` will throw a `TypeError` if you try to cast that. – nuts Mar 11 '20 at 12:22
8

3.0 gives you the option to serialize decimals as floats.

https://github.com/tomchristie/django-rest-framework/blob/version-3.0/docs/topics/3.0-announcement.md#decimals-as-strings-in-serializer-data

REST_FRAMEWORK = {
    'COERCE_DECIMAL_TO_STRING': False
}
Vitor Mascia
  • 109
  • 2
  • 9
4

Floats and decimals are not the same. Don't convert a decimal to a float just to serialize it; you'll lose precision.

Instead just use the DjangoJSONEncoder class which works just fine:

from django.core.serializers import DjangoJSONEncoder
json.dumps(self.earnings, encoder=DjangoJSONEncoder)
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • 3
    I notice that DjangoJSONEncoder is in django.core.serializers.json in django version 1.8 so the statement would be from django.core.serializers.json import DjangoJSONEncoder – vibhor Jul 07 '17 at 11:12
  • 2
    I think the attribute should be **cls** instead of **encoder**. so serializing statement would be something like this **json.dumps(self.earnings, cls=DjangoJSONEncoder)** – vibhor Jul 07 '17 at 12:02
3

Could just have the serializer cast it as a float field.

rest-framework declaring-serializers

from rest_framework import serializers

class DailyReportSerializer(serializers.ModelSerializer):
    earnings = serializers.FloatField()

    class Meta:
        model = DailyReport
        fields = ('earnings',)
B.Adler
  • 1,499
  • 1
  • 18
  • 26