#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 , 11 years ago
comment:2 by , 11 years ago
Cc: | added |
---|
comment:3 by , 11 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 , 11 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 , 11 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 , 11 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 , 11 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 , 11 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
LGTM, fix and test are pretty straightforward.
comment:9 by , 11 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
comment:10 by , 11 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 , 11 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.