6

I'm using Django to create an application (using PostgreSQL) that needs a column numeric(15,6), but I'm not finding a method to do this.

1
  • 1
    What's wrong with a decimal field? Commented Sep 22, 2015 at 15:22

2 Answers 2

13

From PostgreSQL docs:

The types decimal and numeric are equivalent. Both types are part of the SQL standard.

So you can use Django's DecimalField

class MyModel(models.Model):
    my_field = models.DecimalField(max_digits=15, decimal_places=6)

Some docs:

Sign up to request clarification or add additional context in comments.

1 Comment

Can DecimalField be used without specyfing precision and scale so values will be taken with precision and scale as they are in database?
2

Hoping to add onto to the answer but I don't have enough reputation to comment. This is about how to add a Django model field for PostgreSQL NUMERIC type without specifying precision and scale.

As said in the above answer, we have NUMERIC(precision, scale) in postgres. In models.DecimalField(max_digits=15, decimal_places=6), max_digits maps to precision and decimal_places maps to scale.

In the postgres documentation, it says that 'NUMERIC without any precision or scale creates an “unconstrained numeric” column in which numeric values of any length can be stored, up to the implementation limits. A column of this kind will not coerce input values to any particular scale, whereas numeric columns with a declared scale will coerce input values to that scale.'

This means if you have NUMERIC(15,6), if you input 1.2, the data inserted in to postgres will be coerced to 1.200000. But if you have NUMERIC, then the data inserted will be as it is, i.e. 1.2.

I found this great article talking about how you can create a new ArbitraryDecimalField in models.py that overrides the requirement of declaring max_digits and decimal_places in Django models.DecimalField so that we can specify postgres NUMERIC data type without declaring precision and scale. This works when I test with Model.objects.create() to create and save the object directly in the database.

If I want to create the object through a POST request using an API written in Django REST framework, I get errors related to the rest_framework.serializers:

TypeError: __init__() missing 2 required positional arguments: 'max_digits' and 'decimal_places'

Diggging into the django rest framework source code serializers.py and fields.py, to prevent the error in the Django project serializers.py, we need to set max_digits and decimal_places in the serializers.DecimalField as None. Here is a sample.

models.py (based on this great article)

from django.db import models

class ArbitraryDecimalField(models.DecimalField):
    def _check_decimal_places(self):
        return []
    def _check_max_digits(self):
        return []

    def _check_decimal_places_and_max_digits(self):
        return []

    def db_type(self, connection):
        # pg or bust
        assert connection.settings_dict["ENGINE"] == "django.db.backends.postgresql"
        return "numeric"

class SampleModel(models.Model):
    my_num = ArbitraryDecimalField()

serializers.py

from rest_framework import serializers
from models import SampleModel

class SampleSerializer(serializers.ModelSerializer):
    my_num = serializers.DecimalField(max_digits=None, decimal_places=None)
    class Meta:
        model = SampleModel
        fields = ['my_num']

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.