【问题标题】:How should I upgrade from bradjasper's django-jsonfield to Django's built-in jsonfield?我应该如何从 bradjasper 的 django-jsonfield 升级到 Django 的内置 jsonfield?
【发布时间】:2017-05-31 16:54:31
【问题描述】:

我有一个使用 bradjasper 的 django-jsonfield 包的 Postgres 9.4 / Django 1.8 数据库。 (见https://github.com/bradjasper/django-jsonfield )它运行良好,但我想升级现有数据以使用 Postgres 9.6 和 Django 1.9 的内置 JSONField。 (请参阅 https://docs.djangoproject.com/en/1.10/ref/contrib/postgres/fields/#jsonfield )这将允许对 JSON 内容进行更强大的搜索。

如何将旧数据库升级到新数据库?

我尝试过的: 我尝试将一对模式迁移插入到

  • 将 bradjasper JSONField 转换为 TextField,包括运行迁移。 (这不应该更改数据库,因为 bradjasper 将数据存储为字符串。)
  • 运行 Django 的 dumpdata 命令。
  • 更新了 Postgres 和 Django 版本。
  • 运行迁移以将 TextField 转换为 Django 的 JSONField。 (这应该是数据库中的更改,从 textjsonjsonb。)
  • 运行 Django 的loaddata 命令。这会产生如下错误:u"[] (type <type 'unicode'>) is not a valid list for field url_methods"]: (myapp.mytable:pk=1) field_value was '[]' 我正在查看 postgresql migrating JSON to JSONBUpgrade PostgreSQL JSON column to JSONB?,但希望尽量减少自定义 SQL。

【问题讨论】:

  • 您是否还编辑/删除了现有迁移?在加载数据之前?
  • 我在 dumpdata 之前通过 convert-to-textfield 步骤向上运行迁移,然后在 loaddata 之前运行 convert-from-textfield 迁移。编辑了尝试的步骤,使其更加清晰。

标签: json django postgresql jsonb


【解决方案1】:

首先升级 Postgres。如果一切正常,请升级 Django。

只有当一切都按预期工作时,您才能开始编写字段迁移。

你想从:

from jsonfield import JSONField

class MyModel(models.Model):
  json = JSONField()

收件人:

from django.contrib.postgres.fields import JSONField

class MyModel(models.Model):
  json = JSONField()

步骤:

  1. 添加名为 json_new 的新 Postgres JSON 字段。
  2. 进行迁移。不要迁移。
  3. 深入研究迁移文件并编写数据迁移 (RunPython) 以填充新的 json 字段。
  4. 进行迁移。
  5. 删除旧字段。删除旧的导入。
  6. 进行迁移,迁移。
  7. 将新字段重命名为旧字段名称。 json_new > json.
  8. 进行迁移,迁移。
  9. 完成。

第 1 步:

使用import ... as ... 来防止冲突。您的模型将如下所示:

from jsonfield import JSONField as OldJSONField
from django.contrib.postgres.fields import JSONField

class MyModel(models.Model):
  json = OldJSONField()
  json_new = JSONField()

第 3 步:

您需要在迁移中RunPython 参见https://docs.djangoproject.com/en/1.10/ref/migration-operations/#runpython 另请注意如何导入模型。

实际的数据迁移将是这样的:

for obj in MyModel.objects.all()
    obj.json_new = obj.json  
    obj.save()

第 4 - 7 步:

确保为删除和重命名创建单独的迁移。如果您更改了所有代码并创建了一个迁移,那么 Django 会认为您删除了json_new。但是您想删除json 并将json_new 重命名为json。微小但重要的区别。

减少迁移步骤并不难。但这需要手动编写一些代码。我很懒,喜欢 Django 为我写这段代码。

【讨论】:

  • 我很高兴你满足了我在没有自定义 SQL 的情况下执行此操作的软要求,但单个记录的循环让我感到困扰。 (我在不同的表上有几个字段,每个表可能有几千条记录。)SQL 也比我担心的要容易。我放弃竖起大拇指,但接受我自己的答案。
  • 您可以使用F 表达式通过单个查询在RunPython 中执行数据迁移:MyModel.objects.update(json_new=F('json'))
  • 是的! F 可以工作,而且速度更快,数据库负载更少。
【解决方案2】:

来自@tometzky 通过Upgrade PostgreSQL JSON column to JSONB? 的ALTER COLUMN 命令 做到这一点出乎意料的小麻烦:

  • sudo -u postgres psql -c 'ALTER TABLE mytable ALTER COLUMN "myfield" TYPE jsonb USING "myfield"::text::jsonb;'我的数据库

我不需要 Django 的 loaddata / dumpdata 命令或自定义迁移。

我在让 pg_upgrade 按我想要的方式工作时确实遇到了一些问题,因为它不在默认路径上,并且想要在升级期间更改 Postgres 使用的端口。为了解决那个,我做了以下事情:

  • pg_ctl -D /etc/postgresql/9.4/main/stop
  • 在 postgresql.conf 上使用 sed 来更改它使用的端口
  • 安装 Postgres 9.6
  • pg_ctl -D /etc/postgresql/9.6/main/stop
  • cd /var/log/postgresql
  • 运行 pg_upgrade
  • cd 回到原来的工作目录
  • apt-get -y 删除 postgresql-9.4 postgresql-client-9.4 postgresql-server-dev-9.4
  • 服务 postgresql 启动

【讨论】:

    猜你喜欢
    • 2017-07-03
    • 2019-03-09
    • 2017-04-29
    • 2018-10-27
    • 2016-07-23
    • 2016-08-07
    • 2013-01-01
    • 1970-01-01
    相关资源
    最近更新 更多