Reputation: 530
I added a postgres
JsonField
in my model, and created data migration
for it.
new_column = pg_fields.JSONField(default=dict, encoder=DjangoJSONEncoder)
Same logic is used for future data(in save()
of model) and for historic data(data migration).
This is the format of data I am trying to save
data = {
'premium': obj.amount * obj.persons,
}
proposal.new_column = data
proposal.save()
Here, obj
is the instance of some other model, and amount
is the DecimalField
of that model.
The logic runs fine in save()
method of model class.
But on running data migration, I am getting this error
TypeError: Object of type Decimal is not JSON serializable
Stacktrace
Traceback (most recent call last):
File "./manage.py", line 21, in <module>
execute_from_command_line(sys.argv)
File "/home/simarpreet/Envs/j/lib/python3.7/site-packages/django/core/management/__init__.py", line 381, in execute_from_command_line
utility.execute()
File "/home/simarpreet/Envs/j/lib/python3.7/site-packages/django/core/management/__init__.py", line 375, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/simarpreet/Envs/j/lib/python3.7/site-packages/django/core/management/base.py", line 323, in run_from_argv
self.execute(*args, **cmd_options)
File "/home/simarpreet/Envs/j/lib/python3.7/site-packages/django/core/management/base.py", line 364, in execute
output = self.handle(*args, **options)
File "/home/simarpreet/Envs/j/lib/python3.7/site-packages/django/core/management/base.py", line 83, in wrapped
res = handle_func(*args, **kwargs)
File "/home/simarpreet/Envs/j/lib/python3.7/site-packages/django/core/management/commands/migrate.py", line 234, in handle
fake_initial=fake_initial,
File "/home/simarpreet/Envs/j/lib/python3.7/site-packages/django/db/migrations/executor.py", line 117, in migrate
state = self._migrate_all_forwards(state, plan, full_plan, fake=fake, fake_initial=fake_initial)
File "/home/simarpreet/Envs/j/lib/python3.7/site-packages/django/db/migrations/executor.py", line 147, in _migrate_all_forwards
state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
File "/home/simarpreet/Envs/j/lib/python3.7/site-packages/django/db/migrations/executor.py", line 245, in apply_migration
state = migration.apply(state, schema_editor)
File "/home/simarpreet/Envs/j/lib/python3.7/site-packages/django/db/migrations/migration.py", line 124, in apply
operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
File "/home/simarpreet/Envs/j/lib/python3.7/site-packages/django/db/migrations/operations/special.py", line 190, in database_forwards
self.code(from_state.apps, schema_editor)
File "/home/simarpreet/Aegon/jarvis/insurance/travel/proposal/migrations/0006_auto_20191111_1943.py", line 34, in repopulate_slab_in_proposals
proposal.save()
File "/home/simarpreet/Envs/j/lib/python3.7/site-packages/django/db/models/base.py", line 741, in save
force_update=force_update, update_fields=update_fields)
File "/home/simarpreet/Envs/j/lib/python3.7/site-packages/django/db/models/base.py", line 779, in save_base
force_update, using, update_fields,
File "/home/simarpreet/Envs/j/lib/python3.7/site-packages/django/db/models/base.py", line 851, in _save_table
forced_update)
File "/home/simarpreet/Envs/j/lib/python3.7/site-packages/django/db/models/base.py", line 900, in _do_update
return filtered._update(values) > 0
File "/home/simarpreet/Envs/j/lib/python3.7/site-packages/django/db/models/query.py", line 760, in _update
return query.get_compiler(self.db).execute_sql(CURSOR)
File "/home/simarpreet/Envs/j/lib/python3.7/site-packages/django/db/models/sql/compiler.py", line 1429, in execute_sql
cursor = super().execute_sql(result_type)
File "/home/simarpreet/Envs/j/lib/python3.7/site-packages/django/db/models/sql/compiler.py", line 1100, in execute_sql
cursor.execute(sql, params)
File "/home/simarpreet/Envs/j/lib/python3.7/site-packages/django/db/backends/utils.py", line 99, in execute
return super().execute(sql, params)
File "/home/simarpreet/Envs/j/lib/python3.7/site-packages/django/db/backends/utils.py", line 67, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "/home/simarpreet/Envs/j/lib/python3.7/site-packages/django/db/backends/utils.py", line 76, in _execute_with_wrappers
return executor(sql, params, many, context)
File "/home/simarpreet/Envs/j/lib/python3.7/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "/home/simarpreet/Envs/j/lib/python3.7/site-packages/psycopg2/_json.py", line 78, in getquoted
s = self.dumps(self.adapted)
File "/home/simarpreet/Envs/j/lib/python3.7/site-packages/django/contrib/postgres/fields/jsonb.py", line 27, in dumps
return json.dumps(obj, **options)
File "/usr/lib/python3.7/json/__init__.py", line 231, in dumps
return _default_encoder.encode(obj)
File "/usr/lib/python3.7/json/encoder.py", line 199, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/usr/lib/python3.7/json/encoder.py", line 257, in iterencode
return _iterencode(o, 0)
File "/usr/lib/python3.7/json/encoder.py", line 179, in default
raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type Decimal is not JSON serializable
But as per the documentation of Django data migration (https://docs.djangoproject.com/en/2.2/topics/migrations/) , Django can serialze the decimal.Decimal value. Following is the screenshot for reference.
Can someone suggest why am I getting this error?
Upvotes: 1
Views: 1503
Reputation: 530
I was getting this issue because I forgot to run migration after adding the encoder
new_column = pg_fields.JSONField(default=dict, encoder=DjangoJSONEncoder)
Running migration again python manage.py migrate
solved the problem.
Posting the solution in case someone else does such things like me.
Upvotes: 2