Django postgres从CharField到JSONField进行自定义迁移

时间:2018-03-20 14:57:23

标签: django postgresql

我需要改变这个

data = models.CharField(max_length=500, null=True)

到这个

data = JSONField(null=True, blank=True, default={})

据我所知,我必须编写自定义迁移。最近的信息我找到了here,但我完全不知道如何处理RunPython,如果这是正确的事情。

2 个答案:

答案 0 :(得分:0)

您可以在接下来的步骤中执行此操作: 1.添加类型为JSONField的新字段并运行'makemigrations':

data = models.CharField(max_length=500, null=True)
data_json = JSONField(null=True, blank=True, default={})
  1. 创建数据迁移(使用RunPython)
  2. import json
    
    from django.db import migrations
    
    def forwards_func(apps, schema_editor):
        MyModel = apps.get_model("myapp", "MyModel")
    
        for obj in MyModel.objects.all():
            try:
                obj.data_json = json.loads(obj.data)
                obj.save()
            except json.decoder.JSONDecodeError as e:
                print('Cannot convert {} object'.format(obj.pk))
    
    
    class Migration(migrations.Migration):
    
        dependencies = []  # WRITE YOUR LAST MIGRATION HERE
    
        operations = [
            migrations.RunPython(forwards_func, lambda apps, schema_editor: pass),
        ]

    1. 删除旧数据字段并运行'makemigrations':

      data_json = JSONField(null = True,blank = True,默认= {})

    2. 重命名json字段并运行'makemigrations':

      data = JSONField(null = True,blank = True,默认= {})

    3. P.S。您可以对所有这些步骤使用一次迁移。我描述了更好理解的所有步骤。

答案 1 :(得分:0)

假设您有这样的模型

class SampleModel(models.Model):
    name = models.CharField(max_length=120)
    age = models.IntegerField()
    address = models.CharField(max_length=100)


您需要将address更改为JSONField
因此,您必须定义temporary field,如下所示

from django.db import models
from jsonfield import JSONField


class SampleModel(models.Model):
    name = models.CharField(max_length=120)
    age = models.IntegerField()
    address = models.CharField(max_length=100)
    temp_address = JSONField(default={})


然后运行命令,
python manage.py makemigrations app_namepython manage.py migrate app_name

然后是DATA MIGRATION的角色。你需要做的是,运行命令python manage.py makemigrations app_name --empty
这将在您的目录中创建一个empty migration file。将该文件更改为此类的内容 0003_auto_20180320_1525.py (迁移文件)

# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2018-03-20 15:25
from __future__ import unicode_literals
import json
from django.db import migrations
from sample.models import SampleModel


class Migration(migrations.Migration):
    def forward_data_migration(apps, schema):
        for sample in SampleModel.objects.all():
            try:
                sample.temp_address = json.loads(sample.address)
                sample.save()
            except json.decoder.JSONDecodeError as e:
                print('Cannot convert {} object'.format(sample.pk))

    def revert_migration(apps, schema):
        pass

    dependencies = [
        ('sample', '0002_samplemodel_temp_address'),
    ]

    operations = [
        migrations.RunPython(
            code=forward_data_migration,
            reverse_code=revert_migration
        )
    ]


迁移此更改,然后像以前一样创建另一个空迁移文件,并编写RenameField脚本,如下所示 的 0004_auto_20180320_1530.py

# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2018-03-20 15:30
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):
    dependencies = [
        ('sample', '0003_auto_20180320_1525'),
    ]

    operations = [
        migrations.RenameField(
            model_name='samplemodel',
            old_name='address',
            new_name='temp_address'
        ),
        migrations.RenameField(
            model_name='samplemodel',
            old_name='temp_address',
            new_name='address'
        )

    ]


也移植这个。就是这样。