#22272 closed Bug (fixed)
model.DecimalField with decimal_places=0
| Reported by: | merb | Owned by: | nobody |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 1.7-alpha-2 |
| Severity: | Release blocker | Keywords: | |
| Cc: | merb | Triage Stage: | Ready for checkin |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
Currently I can't create DecimalField with decimal_places=0 on Postgresql with psycopg2 (sqlite3 works as expected)
In PostgreSQL I can create numeric fields with a scale of zero: http://www.postgresql.org/docs/9.3/static/datatype-numeric.html
But the current implementation disallows this: (The Exception I hit)
Running migrations:
Applying envisia_article.0001_initial...DEBUG:django.db.backends:(0.002)
SELECT c.relname
FROM pg_catalog.pg_class c
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind IN ('r', 'v', '')
AND n.nspname NOT IN ('pg_catalog', 'pg_toast')
AND pg_catalog.pg_table_is_visible(c.oid); args=None
DEBUG:django.db.backends.schema:CREATE TABLE "envisia_article_solderresist" ("id" serial NOT NULL PRIMARY KEY, "name" varchar(100) NULL, "name_en" varchar(100) NULL); (params [])
DEBUG:django.db.backends:(0.003) CREATE TABLE "envisia_article_solderresist" ("id" serial NOT NULL PRIMARY KEY, "name" varchar(100) NULL, "name_en" varchar(100) NULL); args=[]
DEBUG:django.db.backends.schema:CREATE TABLE "envisia_article_bestpressurecolor" ("id" serial NOT NULL PRIMARY KEY, "name" varchar(100) NULL, "name_en" varchar(100) NULL); (params [])
DEBUG:django.db.backends:(0.001) CREATE TABLE "envisia_article_bestpressurecolor" ("id" serial NOT NULL PRIMARY KEY, "name" varchar(100) NULL, "name_en" varchar(100) NULL); args=[]
DEBUG:django.db.backends.schema:CREATE TABLE "envisia_article_cuinside" ("id" serial NOT NULL PRIMARY KEY, "value" numeric(10, None) NOT NULL); (params [])
DEBUG:django.db.backends:(0.001) CREATE TABLE "envisia_article_cuinside" ("id" serial NOT NULL PRIMARY KEY, "value" numeric(10, None) NOT NULL); args=[]
Traceback (most recent call last):
File "/Users/schmitch/Programme/virtualenv/envisia_dashboard/lib/python3.3/site-packages/Django-1.7a2-py3.3.egg/django/db/backends/utils.py", line 61, in execute
return self.cursor.execute(sql, params)
psycopg2.DataError: invalid input syntax for integer: "none"
LINE 1: ...nside" ("id" serial NOT NULL PRIMARY KEY, "value" numeric(10...
^
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "./manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/Users/schmitch/Programme/virtualenv/envisia_dashboard/lib/python3.3/site-packages/Django-1.7a2-py3.3.egg/django/core/management/__init__.py", line 427, in execute_from_command_line
utility.execute()
File "/Users/schmitch/Programme/virtualenv/envisia_dashboard/lib/python3.3/site-packages/Django-1.7a2-py3.3.egg/django/core/management/__init__.py", line 419, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/Users/schmitch/Programme/virtualenv/envisia_dashboard/lib/python3.3/site-packages/Django-1.7a2-py3.3.egg/django/core/management/base.py", line 287, in run_from_argv
self.execute(*args, **options.__dict__)
File "/Users/schmitch/Programme/virtualenv/envisia_dashboard/lib/python3.3/site-packages/Django-1.7a2-py3.3.egg/django/core/management/base.py", line 336, in execute
output = self.handle(*args, **options)
File "/Users/schmitch/Programme/virtualenv/envisia_dashboard/lib/python3.3/site-packages/Django-1.7a2-py3.3.egg/django/core/management/commands/migrate.py", line 145, in handle
executor.migrate(targets, plan, fake=options.get("fake", False))
File "/Users/schmitch/Programme/virtualenv/envisia_dashboard/lib/python3.3/site-packages/Django-1.7a2-py3.3.egg/django/db/migrations/executor.py", line 60, in migrate
self.apply_migration(migration, fake=fake)
File "/Users/schmitch/Programme/virtualenv/envisia_dashboard/lib/python3.3/site-packages/Django-1.7a2-py3.3.egg/django/db/migrations/executor.py", line 94, in apply_migration
migration.apply(project_state, schema_editor)
File "/Users/schmitch/Programme/virtualenv/envisia_dashboard/lib/python3.3/site-packages/Django-1.7a2-py3.3.egg/django/db/migrations/migration.py", line 97, in apply
operation.database_forwards(self.app_label, schema_editor, project_state, new_state)
File "/Users/schmitch/Programme/virtualenv/envisia_dashboard/lib/python3.3/site-packages/Django-1.7a2-py3.3.egg/django/db/migrations/operations/models.py", line 28, in database_forwards
schema_editor.create_model(model)
File "/Users/schmitch/Programme/virtualenv/envisia_dashboard/lib/python3.3/site-packages/Django-1.7a2-py3.3.egg/django/db/backends/schema.py", line 243, in create_model
self.execute(sql, params)
File "/Users/schmitch/Programme/virtualenv/envisia_dashboard/lib/python3.3/site-packages/Django-1.7a2-py3.3.egg/django/db/backends/schema.py", line 95, in execute
cursor.execute(sql, params)
File "/Users/schmitch/Programme/virtualenv/envisia_dashboard/lib/python3.3/site-packages/Django-1.7a2-py3.3.egg/django/db/backends/utils.py", line 77, in execute
return super(CursorDebugWrapper, self).execute(sql, params)
File "/Users/schmitch/Programme/virtualenv/envisia_dashboard/lib/python3.3/site-packages/Django-1.7a2-py3.3.egg/django/db/backends/utils.py", line 61, in execute
return self.cursor.execute(sql, params)
File "/Users/schmitch/Programme/virtualenv/envisia_dashboard/lib/python3.3/site-packages/Django-1.7a2-py3.3.egg/django/db/utils.py", line 93, in __exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)
File "/Users/schmitch/Programme/virtualenv/envisia_dashboard/lib/python3.3/site-packages/Django-1.7a2-py3.3.egg/django/utils/six.py", line 535, in reraise
raise value.with_traceback(tb)
File "/Users/schmitch/Programme/virtualenv/envisia_dashboard/lib/python3.3/site-packages/Django-1.7a2-py3.3.egg/django/db/backends/utils.py", line 61, in execute
return self.cursor.execute(sql, params)
django.db.utils.DataError: invalid input syntax for integer: "none"
LINE 1: ...nside" ("id" serial NOT NULL PRIMARY KEY, "value" numeric(10...
^
As you can see, since I've runnning with debug is that numeric() is numeric(10, None) instead of numeric(10) or numeric(10, 0).
Which is a bug and shouldn't occur.
Change History (11)
comment:1 by , 12 years ago
comment:2 by , 12 years ago
| Cc: | added |
|---|
comment:3 by , 12 years ago
| Triage Stage: | Unreviewed → Accepted |
|---|
I'm able to reproduce the issue using this simple model:
class Foo(models.Model): foo = models.DecimalField(max_digits=7, decimal_places=0)
As noted, this works in 1.6 so the release blocker flag is warranted too.
comment:4 by , 12 years ago
| Has patch: | set |
|---|---|
| Needs tests: | set |
The following patch seems to fix the issue (you have to regenerate the migration file):
-
django/db/models/fields/__init__.py
diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py index 16a0700..dd88471 100644
a b class DecimalField(Field): 1379 1379 1380 1380 def deconstruct(self): 1381 1381 name, path, args, kwargs = super(DecimalField, self).deconstruct() 1382 if self.max_digits :1382 if self.max_digits is not None: 1383 1383 kwargs['max_digits'] = self.max_digits 1384 if self.decimal_places :1384 if self.decimal_places is not None: 1385 1385 kwargs['decimal_places'] = self.decimal_places 1386 1386 return name, path, args, kwargs
comment:5 by , 12 years ago
| Patch needs improvement: | set |
|---|
Currently this patch needs improvement since:
max_digits needs to be positive in the PostgreSQL documentation (I think in other databases this max_digits needs to be positive as well)
http://www.postgresql.org/docs/9.3/static/datatype-numeric.html
Also MySQL needs a positive value for max_digits aswell. Only decimal_places could be zero or positive.
http://www.postgresql.org/docs/9.3/static/datatype-numeric.html
comment:6 by , 12 years ago
This patch only fixes the regression, but unless I'm mistaken, earlier versions of Django don't validate the value of max_digits, do they?
This should be a separate ticket imho.
comment:7 by , 12 years ago
| Needs tests: | unset |
|---|---|
| Patch needs improvement: | unset |
Actually, there are already checks in place to make sure max_digits>0 and decimal_places>=0: https://github.com/django/django/blob/master/django/db/models/fields/__init__.py#L1342
So I'm not sure I understand what comment:5 is referring to.
I've got a patch with tests now ready for committing: https://github.com/bmispelon/django/commit/37f7f233f5f30c28ea60a7fbc272ffd296e2dbe1
Any objection to me pushing it?
comment:8 by , 12 years ago
| Triage Stage: | Accepted → Ready for checkin |
|---|
LGTM, fix and test are pretty straightforward.
comment:9 by , 12 years ago
| Resolution: | → fixed |
|---|---|
| Status: | new → closed |
comment:10 by , 12 years ago
| Needs tests: | set |
|---|---|
| Patch needs improvement: | set |
| Triage Stage: | Ready for checkin → Accepted |
Oh thanks, i didn't saw the checks. Currently I was really busy.
Btw. thanks for the quick fix. ;)
comment:11 by , 12 years ago
| Has patch: | unset |
|---|---|
| Needs tests: | unset |
| Patch needs improvement: | unset |
| Triage Stage: | Accepted → Ready for checkin |
Django 1.6 will work and make the model to numeric(10, 0) even South worked like this and made it from numeric(10, X) to numeric(10, 0) if i changed the value.