【问题标题】:Django Migrate from Char Field to Integer Field?Django 从字符字段迁移到整数字段?
【发布时间】:2019-03-30 18:39:15
【问题描述】:

我在 models.py:: 中更改了我的 CharField 之一

models.CharField(max_length=128, blank=True)

进入 IntegerField -->

models.IntegerField(default=0)

我有该字段的数据,主要是空字符串("")或整数作为字符串(例如:"10")。

所以我想在迁移时将这些字符串转换为整数。例如:: 如果空字符串("")转换为0,否则转换为整数。

当我执行./manage.py migrate 命令时,我怎样才能做到这一点?

这里是使用./manage.py makemigrations:: 创建的迁移文件

# Generated by Django 2.1.2 on 2018-10-25 04:57

from django.db import migrations, models


class Migration(migrations.Migration):

    dependencies = [
        ('dashboard', '0002_auto_20181024_1544'),
    ]

    operations = [
        migrations.AlterField(
            model_name='aclpermissions',
            name='ordering',
            field=models.IntegerField(default=0),
        ),
        migrations.AlterField(
            model_name='submenus',
            name='ordering',
            field=models.IntegerField(default=0),
        ),
        migrations.AlterField(
            model_name='subsubmenus',
            name='ordering',
            field=models.IntegerField(default=0),
        ),
    ]

当我运行./manage.py migrate 时出现错误::

psycopg2.DataError: invalid input syntax for integer: ""

因为有空字符串""的字段。

所以我想将空字符串("")转换为0

【问题讨论】:

  • 您将我的 CharField 之一更改为 IntegerField。哪一个?您的迁移文件显示您更改了 3 个字段。
  • @RedCricket 我将 3 个字符字段更改为整数字段。我通过将db中的所有empty strings更新为0解决了这个问题。现在./manage.py migrate 命令工作正常。
  • 你的意思是你把所有的空值都更新为字符串“0”了吗?
  • @RedCricket 是的。更新后我运行./manage.py migrate,它工作正常。
  • 我将首先创建 3 个新字段并编写 data migration,然后运行第二次迁移,将这 3 个字段重命名。

标签: python django migration


【解决方案1】:

对于其他遇到此问题的人,您可以添加一个函数以在其他迁移操作之前运行:

class Migration(migrations.Migration):

    def blank_to_zero(apps, schema_editor):
        AclPermissions = apps.get_model('dashboard', 'AclPermissions')
        SubMenus = apps.get_model('dashboard', 'SubMenus')
        SubSubMenus = apps.get_model('dashboard', 'SubSubMenus')

        for obj in AclPermissions.objects.filter(ordering=''):
            obj.ordering = 0
            obj.save()

        for obj in SubMenus.objects.filter(ordering=''):
            obj.ordering = 0
            obj.save()

        for obj in SubSubMenus.objects.filter(ordering=''):
            obj.ordering = 0
            obj.save()

    dependencies = [
        ('dashboard', '0002_auto_20181024_1544'),
    ]

    operations = [
        migrations.RunPython(blank_to_zero),

        migrations.AlterField(... 
        # the rest of your operations
    ]

有关编辑数据迁移的信息,请参阅 https://docs.djangoproject.com/en/dev/topics/migrations/#data-migrations

【讨论】:

  • 减少到每个模型的单个查询:AclPermissions.objects.filter(ordering='').update(ordering=0)。如果有很多对象会节省很多时间。
【解决方案2】:

字符/旧:

email_type = models.CharField(max_length=50, default=None)

将其更改为 Int/New:

email_type = models.IntegerField(default=None)
  • python manage.py makemigration

改变方式:

  1. 通过丢失数据(简单方法)

Revert迁移到以前的版本

  1. 不丢失数据(更难的方法)

打开 Python shell 或编写脚本以 -- 将 'email_type' 的每个值更改为数字(如 0、1、2、3...)

然后

  • python manage.py 迁移

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-10
    • 2012-01-01
    • 1970-01-01
    • 2012-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-21
    相关资源
    最近更新 更多