如何从bradjasper升级';s django jsonfield至django';s内置的jsonfield?

如何从bradjasper升级';s django jsonfield至django';s内置的jsonfield?,json,django,postgresql,jsonb,Json,Django,Postgresql,Jsonb,我有一个Postgres9.4/Django1.8数据库,它使用bradjasper的DjangoJSonfield包。(请参阅)它工作得很好,但我想升级现有数据以使用Postgres 9.6和Django 1.9的内置JSONField。(请参阅)这将允许对JSON内容进行更健壮的搜索 如何将旧数据库升级到新数据库 我所尝试的: 我尝试将一对模式迁移插入到 将bradjasper JSONField转换为文本字段,包括运行迁移。(这不应改变数据库,因为bradjasper将数据存储为字符串。

我有一个Postgres9.4/Django1.8数据库,它使用bradjasper的
DjangoJSonfield
包。(请参阅)它工作得很好,但我想升级现有数据以使用Postgres 9.6和Django 1.9的内置JSONField。(请参阅)这将允许对JSON内容进行更健壮的搜索

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

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

  • 将bradjasper JSONField转换为文本字段,包括运行迁移。(这不应改变数据库,因为bradjasper将数据存储为字符串。)
  • 运行Django的
    dumpdata
    命令
  • 更新了Postgres和Django版本
  • 运行迁移以将TextField转换为Django的JSONField。(这应该是数据库中的更改,从
    text
    json
    更改为
    jsonb
  • 运行Django的
    loaddata
    命令。这会出现如下错误:
    u“[](类型)不是字段url\u方法的有效列表]:(myapp.mytable:pk=1)字段\u值为“[]”
    我正在查看,但希望尽量减少自定义SQL

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

只有当一切按预期进行时,您才能开始编写字段迁移

您想从以下位置开始:

from jsonfield import JSONField

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

步骤:

  • 添加名为
    JSON\u new
    的新Postgres JSON字段
  • 进行迁移。不要迁移
  • 深入迁移文件并编写数据迁移(RunPython)以填充新的json字段
  • 进行迁移
  • 删除旧字段。删除旧的导入
  • 进行迁移,迁移
  • 将新字段重命名为旧字段名
    json\u new
    json
  • 进行迁移,迁移
  • 完成了
  • 步骤1:

    使用
    导入。。。作为…
    以防止碰撞。您的模型将如下所示:

    from jsonfield import JSONField as OldJSONField
    from django.contrib.postgres.fields import JSONField
    
    class MyModel(models.Model):
      json = OldJSONField()
      json_new = JSONField()
    
    步骤3:

    您需要在迁移中
    运行Python
    ,请参见 还要注意如何导入模型

    实际的数据迁移类似于:

    for obj in MyModel.objects.all()
        obj.json_new = obj.json  
        obj.save()
    
    步骤4-7:

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


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

    来自@tometzky via的ALTER COLUMN命令 这样做的麻烦小得出奇:

    • sudo-u postgres psql-c'ALTER TABLE mytable ALTER COLUMN“myfield”使用“myfield”键入jsonb::text::jsonb;'我的数据库
    我不需要Django的loaddata/dumpdata命令或自定义迁移

    我确实遇到了一些问题,让pg_升级以我想要的方式工作,因为它不在默认路径上,并且希望在升级期间更改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
    • 运行pgu升级
    • cd返回到原始工作目录
    • apt get-y删除postgresql-9.4 postgresql-client-9.4 postgresql-server-dev-9.4
    • postgresql启动服务

    您是否也编辑/删除了现有迁移?在执行loaddata之前?我在dumpdata之前通过convert to textfield步骤向上运行迁移,然后在loaddata之前运行convert from textfield迁移。我喜欢你满足了我在没有自定义SQL的情况下这样做的软要求,但是对单个记录的循环让我很烦恼。(我在不同的表上有几个字段,每个表可能有几千条记录。)而且SQL结果比我担心的要简单。我竖起大拇指,但接受我自己的答案。您可以使用
    F
    表达式
    MyModel.objects.update(json\u new=F('json'))在
    RunPython
    中执行数据迁移,只需一次查询即可
    F
    将起作用,速度更快,数据库上的负载更少。
    for obj in MyModel.objects.all()
        obj.json_new = obj.json  
        obj.save()