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解决了问题。

发布解决方案以防其他人像我一样这样做。