如何将我的models.TextField更改为models.JSONField?

问题描述

我使用django作为后端,并且运行良好,但是在尝试替换 text = models.TextField(blank=True,null=True) text = models.JSONField(blank=True,null=True)之后,我得到了 文本字段显示为带斜杠\

的字符串

"text": "{\"name\": [\"test\",\"test2\"]}", 而样式字段看起来像json

        "style": {
            "borderRadius": "5px","backgroundColor": "orange"
        },

尽管它们都是jsonfield。

models.py

class elements(models.Model):
    tag = models.CharField(blank=True,null=True,max_length=20)

# it was # text = models.TextField(blank=True,null=True)
# Now it is 
text = models.JSONField(blank=True,null=True)

    src = models.TextField(blank=True,null=True)

    style = models.JSONField(blank=True,null=True)

    main = models.ForeignKey(
        'self',blank=True,related_name="sub",on_delete=models.PROTECT)

    def __str__(self):
        return "<elements: {} {}>".format(self.tag,self.text,self.src,self.style)

    def __repr__(self):
        return self.__str__()

在运行python manage.py makemigrations然后python manage.py migrate之后,我也遇到了错误

DETAIL:  Token "add" is invalid.
CONTEXT:  JSON data,line 1: add...

the full error

Operations to perform:
  Apply all migrations: account,admin,auth,authtoken,contenttypes,myapp,sessions,sites
Running migrations:
  Applying myapp.0006_auto_20200905_1410...Traceback (most recent call last):
  File "/Users/apple/Desktop/learning web stack from clonning notion.so/backend/env/lib/python3.7/site-packages/django/db/backends/utils.py",line 84,in _execute
    return self.cursor.execute(sql,params)
psycopg2.errors.InvalidTextRepresentation: invalid input Syntax for type json
DETAIL:  Token "add" is invalid.
CONTEXT:  JSON data,line 1: add...


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "manage.py",line 22,in <module>
    main()
  File "manage.py",line 18,in main
    execute_from_command_line(sys.argv)
  File "/Users/apple/Desktop/learning web stack from clonning notion.so/backend/env/lib/python3.7/site-packages/django/core/management/__init__.py",line 401,in execute_from_command_line
    utility.execute()
  File "/Users/apple/Desktop/learning web stack from clonning notion.so/backend/env/lib/python3.7/site-packages/django/core/management/__init__.py",line 395,in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/Users/apple/Desktop/learning web stack from clonning notion.so/backend/env/lib/python3.7/site-packages/django/core/management/base.py",line 330,in run_from_argv
    self.execute(*args,**cmd_options)
  File "/Users/apple/Desktop/learning web stack from clonning notion.so/backend/env/lib/python3.7/site-packages/django/core/management/base.py",line 371,in execute
    output = self.handle(*args,**options)
  File "/Users/apple/Desktop/learning web stack from clonning notion.so/backend/env/lib/python3.7/site-packages/django/core/management/base.py",line 85,in wrapped
    res = handle_func(*args,**kwargs)
  File "/Users/apple/Desktop/learning web stack from clonning notion.so/backend/env/lib/python3.7/site-packages/django/core/management/commands/migrate.py",line 245,in handle
    fake_initial=fake_initial,File "/Users/apple/Desktop/learning web stack from clonning notion.so/backend/env/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 "/Users/apple/Desktop/learning web stack from clonning notion.so/backend/env/lib/python3.7/site-packages/django/db/migrations/executor.py",line 147,in _migrate_all_forwards
    state = self.apply_migration(state,migration,line 227,in apply_migration
    state = migration.apply(state,schema_editor)
  File "/Users/apple/Desktop/learning web stack from clonning notion.so/backend/env/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 "/Users/apple/Desktop/learning web stack from clonning notion.so/backend/env/lib/python3.7/site-packages/django/db/migrations/operations/fields.py",line 236,in database_forwards
    schema_editor.alter_field(from_model,from_field,to_field)
  File "/Users/apple/Desktop/learning web stack from clonning notion.so/backend/env/lib/python3.7/site-packages/django/db/backends/base/schema.py",line 572,in alter_field
    old_db_params,new_db_params,strict)
  File "/Users/apple/Desktop/learning web stack from clonning notion.so/backend/env/lib/python3.7/site-packages/django/db/backends/postgresql/schema.py",line 168,in _alter_field
    new_db_params,strict,File "/Users/apple/Desktop/learning web stack from clonning notion.so/backend/env/lib/python3.7/site-packages/django/db/backends/base/schema.py",line 726,in _alter_field
    params,line 142,in execute
    cursor.execute(sql,params)
  File "/Users/apple/Desktop/learning web stack from clonning notion.so/backend/env/lib/python3.7/site-packages/django/db/backends/utils.py",line 98,in execute
    return super().execute(sql,line 66,in execute
    return self._execute_with_wrappers(sql,params,many=False,executor=self._execute)
  File "/Users/apple/Desktop/learning web stack from clonning notion.so/backend/env/lib/python3.7/site-packages/django/db/backends/utils.py",line 75,in _execute_with_wrappers
    return executor(sql,many,context)
  File "/Users/apple/Desktop/learning web stack from clonning notion.so/backend/env/lib/python3.7/site-packages/django/db/backends/utils.py",params)
  File "/Users/apple/Desktop/learning web stack from clonning notion.so/backend/env/lib/python3.7/site-packages/django/db/utils.py",line 90,in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/Users/apple/Desktop/learning web stack from clonning notion.so/backend/env/lib/python3.7/site-packages/django/db/backends/utils.py",params)
django.db.utils.DataError: invalid input Syntax for type json
DETAIL:  Token "add" is invalid.
CONTEXT:  JSON data,line 1: add...
  • 注意:我试图删除我的数据并也进行迁移,但是没有用
  • 注意:我正在使用postgresql

解决方法

为了将Text-Field转换为JSON-Field,您可以使用类似于以下内容的4步策略:

  • 在模型中创建一个新的JSON列
  • 使用--empty添加新的迁移,并使用RunPython运行python函数,以选择整个模型,加载旧的旧值,然后使用json.loads将其转换为JSON对象并保存在新列中
  • 删除旧的“文本字段”列
  • 将较新的列重命名为原始列名