TypeError: Object of type Decimal is not JSON serializable during Django data migration
TypeError: Object of type Decimal is not JSON serializable during Django data migration
我在我的模型中添加了一个 postgres
JsonField
,并为其创建了 data migration
。
new_column = pg_fields.JSONField(default=dict, encoder=DjangoJSONEncoder)
未来数据(在模型 save()
中)和历史数据(数据迁移)使用相同的逻辑。
这是我要保存的数据格式
data = {
'premium': obj.amount * obj.persons,
}
proposal.new_column = data
proposal.save()
这里,obj
是其他模型的实例,amount
是那个模型的DecimalField
。
逻辑在模型 class 的 save()
方法中运行良好。
但是在 运行 数据迁移时,我收到了这个错误
TypeError: Object of type Decimal is not JSON serializable
堆栈跟踪
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
但是根据 Django 数据迁移 (https://docs.djangoproject.com/en/2.2/topics/migrations/) 的文档,Django 可以序列化 decimal.Decimal 值。以下是截图供参考。
有人可以告诉我为什么会出现此错误吗?
我遇到这个问题是因为我在添加编码器后忘记了 运行 迁移
new_column = pg_fields.JSONField(default=dict, encoder=DjangoJSONEncoder)
运行再次迁移python manage.py migrate
解决了问题。
发布解决方案以防其他人像我一样这样做。
我在我的模型中添加了一个 postgres
JsonField
,并为其创建了 data migration
。
new_column = pg_fields.JSONField(default=dict, encoder=DjangoJSONEncoder)
未来数据(在模型 save()
中)和历史数据(数据迁移)使用相同的逻辑。
这是我要保存的数据格式
data = {
'premium': obj.amount * obj.persons,
}
proposal.new_column = data
proposal.save()
这里,obj
是其他模型的实例,amount
是那个模型的DecimalField
。
逻辑在模型 class 的 save()
方法中运行良好。
但是在 运行 数据迁移时,我收到了这个错误
TypeError: Object of type Decimal is not JSON serializable
堆栈跟踪
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
但是根据 Django 数据迁移 (https://docs.djangoproject.com/en/2.2/topics/migrations/) 的文档,Django 可以序列化 decimal.Decimal 值。以下是截图供参考。
有人可以告诉我为什么会出现此错误吗?
我遇到这个问题是因为我在添加编码器后忘记了 运行 迁移
new_column = pg_fields.JSONField(default=dict, encoder=DjangoJSONEncoder)
运行再次迁移python manage.py migrate
解决了问题。
发布解决方案以防其他人像我一样这样做。