Django 1.9删除迁移中的外键

时间:2016-07-11 16:07:50

标签: django foreign-keys database-migration django-1.9

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

class Example(models.Model)
   something = models.ForeignKey(SomeModel, db_index=True)

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

因此模型将变为:

class Example(models.Model):
   something_id = models.IntegerField() 

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

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

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

3 个答案:

答案 0 :(得分:10)

这就是我设法做到的,它是基于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
        )
    ]

答案 1 :(得分:6)

See SeparateDatabaseAndState. It allows you to specify a Django (state) part of the migration separately from the database part of the migration.

  1. Amend the field in your models file.
  2. Create the migration, as normal. You will end up with something like:

    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)),
            ),
        ]
    
  3. Now manually amend this to:

    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)
        ]
    

Note that you are not specifying any database_operations argument, so the Django relationships are amended, but the database data is unchanged.

Needless to say: take a backup before you try this.

答案 2 :(得分:2)

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