Field.get_default() returning dict instance causing migration to fail

89 views
Skip to first unread message

Martin Tiršel

unread,
May 5, 2014, 7:35:33 PM5/5/14
to django-d...@googlegroups.com
Hello,

I just installed 1.7 (pip install git+https://github.com/django/django@stable/1.7.x) and the django-jsonfield app. As you can see here, JSONField.get_default() returns a dict instance, not a string:

https://bitbucket.org/schinckel/django-jsonfield/src/28c51eb06a65c1e7b5d8022031aebb034e0c129c/jsonfield/fields.py?at=default#cl-58

I created a model with:

data = JSONField(default='{}')

ran makemigrations and migrate with this result:

Running migrations:
  Applying account.0002_user_data...Traceback (most recent call last):
  File "./manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "/home/bruce/.virtualenv/paddle/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 427, in execute_from_command_line
    utility.execute()
  File "/home/bruce/.virtualenv/paddle/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 419, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/bruce/.virtualenv/paddle/local/lib/python2.7/site-packages/django/core/management/base.py", line 288, in run_from_argv
    self.execute(*args, **options.__dict__)
  File "/home/bruce/.virtualenv/paddle/local/lib/python2.7/site-packages/django/core/management/base.py", line 337, in execute
    output = self.handle(*args, **options)
  File "/home/bruce/.virtualenv/paddle/local/lib/python2.7/site-packages/django/core/management/commands/migrate.py", line 146, in handle
    executor.migrate(targets, plan, fake=options.get("fake", False))
  File "/home/bruce/.virtualenv/paddle/local/lib/python2.7/site-packages/django/db/migrations/executor.py", line 60, in migrate
    self.apply_migration(migration, fake=fake)
  File "/home/bruce/.virtualenv/paddle/local/lib/python2.7/site-packages/django/db/migrations/executor.py", line 94, in apply_migration
    migration.apply(project_state, schema_editor)
  File "/home/bruce/.virtualenv/paddle/local/lib/python2.7/site-packages/django/db/migrations/migration.py", line 97, in apply
    operation.database_forwards(self.app_label, schema_editor, project_state, new_state)
  File "/home/bruce/.virtualenv/paddle/local/lib/python2.7/site-packages/django/db/migrations/operations/fields.py", line 36, in database_forwards
    field,
  File "/home/bruce/.virtualenv/paddle/local/lib/python2.7/site-packages/django/db/backends/schema.py", line 379, in add_field
    if isinstance(field, ManyToManyField) and field.rel.through._meta.auto_created:
  File "/home/bruce/.virtualenv/paddle/local/lib/python2.7/site-packages/django/db/backends/schema.py", line 98, in execute
    cursor.execute(sql, params)
  File "/home/bruce/.virtualenv/paddle/local/lib/python2.7/site-packages/django/db/backends/utils.py", line 81, in execute
    return super(CursorDebugWrapper, self).execute(sql, params)
  File "/home/bruce/.virtualenv/paddle/local/lib/python2.7/site-packages/django/db/backends/utils.py", line 65, in execute
    return self.cursor.execute(sql, params)
  File "/home/bruce/.virtualenv/paddle/local/lib/python2.7/site-packages/django/db/utils.py", line 94, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "/home/bruce/.virtualenv/paddle/local/lib/python2.7/site-packages/django/db/backends/utils.py", line 65, in execute
    return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: can't adapt type 'dict'

These are the variables:

params: [{}]
sql: u'ALTER TABLE "account_user" ADD COLUMN "data" text DEFAULT %s NOT NULL'

Variable params contains a list with single item - dictionary instance - the default value of JSONField. This seems that if Field.get_default() returns something else than a string (or whatever psycopg2 accepts), the db backend fails. Now the question - should Field.get_default() always return a string (and thus the bug is in django-jsonfield app) or should Django handle this somehow? Should not the Field.get_prep_value() be called before? Regarding this reference - https://code.djangoproject.com/ticket/8633#comment:2 the get_default() method can return anything.

Thanks,
Martin

Andrew Godwin

unread,
May 5, 2014, 7:40:25 PM5/5/14
to django-d...@googlegroups.com
The main problem here is defaults being used for schema definition versus being used for data insertion. The latter runs through the full ORM and the correct methods to convert it to a database value through the field; the former does not, I believe, so this is probably (another) release-blocking bug in Django.

If you could file it in the issue tracker that'd be great; I'll get around to dealing with it when I get to my free time on Wednesday.

Andrew


--
You received this message because you are subscribed to the Google Groups "Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To post to this group, send email to django-d...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/7056dead-0477-45e0-9463-5042a2f5dd51%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages