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.
2 Answers
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:
1 Comment
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']