Django 1.9在迁移中删除了外键

J. *_*Doe 7 django foreign-keys database-migration django-1.9

我有一个Django模型,具有另一个模型的外键:

class Example(models.Model)
   something = models.ForeignKey(SomeModel, db_index=True)
Run Code Online (Sandbox Code Playgroud)

我想将基础数据库列保留为字段,但要删除数据库中的外键约束.

所以模型将变为:

class Example(models.Model):
   something_id = models.IntegerField() 
Run Code Online (Sandbox Code Playgroud)

而且,要清楚的something_id是,Django为外键字段创建的列.

我不想删除列并重新创建它(这是Django在更改模型后自动生成迁移时所执行的操作).

我想保留该字段,我想通过迁移删除数据库中的外键约束.我不清楚如何使用Django迁移实现这一点 - 是否有一些内置的支持或者我必须运行一些原始SQL,如果是这样,我如何以编程方式获取约束的名称?

J. *_*Doe 11

这就是我设法做到的,它基于nimasmi的答案:

class Migration(migrations.Migration):
    dependencies = [
        ('my_app', '0001_initial'),
    ]

    # These *WILL* impact the database!
    database_operations = [
        migrations.AlterField(
            model_name='Example',
            name='something',
            field=models.ForeignKey('Something', db_constraint=False, db_index=True, null=False)
        ),
    ]

    # These *WON'T* impact the database, they update Django state *ONLY*!
    state_operations = [
        migrations.AlterField(
            model_name='Example',
            name='something',
            field=models.IntegerField(db_index=True, null=False)
        ),
        migrations.RenameField(
            model_name='Example',
            old_name='something',
            new_name='something_id'
        ),
    ]

    operations = [
        migrations.SeparateDatabaseAndState(
            database_operations=database_operations,
            state_operations=state_operations
        )
    ]
Run Code Online (Sandbox Code Playgroud)


nim*_*smi 6

请参见SeparateDatabaseAndState.它允许您分别从迁移的数据库部分指定迁移的Django(状态)部分.

  1. 修改模型文件中的字段.
  2. 像往常一样创建迁移.你会得到类似的东西:

    class Migration(migrations.Migration):
    
        dependencies = [
            ('my_app', '0001_whatever.py'),
        ]
    
        operations = [
            migrations.AlterField(
                model_name='example',
                name='something',
                field=models.CharField(max_length=255, null=True)),
            ),
        ]
    
    Run Code Online (Sandbox Code Playgroud)
  3. 现在手动将其修改为:

    class Migration(migrations.Migration):
    
        dependencies = [
            ('my_app', '0001_whatever.py'),
        ]
    
        state_operations = [
            migrations.AlterField(
                model_name='example',
                name='something',
                field=models.CharField(max_length=255, null=True)),
            ),
        ]
        operations = [
            migrations.SeparateDatabaseAndState(state_operations=state_operations)
        ]
    
    Run Code Online (Sandbox Code Playgroud)

请注意,您没有指定任何database_operations参数,因此修改了Django关系,但数据库数据未更改.

不用说:在尝试之前先备份一下.


bto*_*own 5

从 Django 2.0 开始,将字段更改为models.ForeignKey(db_constraint=False, db_index=False, ...)将生成执行 ALTER TABLE DROP CONSTRAINT 和 DROP INDEX IF EXISTS 的迁移,这似乎正是您想要的。