Django 1.9 在迁移中删除外键
Django 1.9 drop foreign key in migration
我有一个 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,如果是这样,我如何以编程方式获得约束名称?
参见 SeparateDatabaseAndState。它允许您从数据库中单独指定迁移的 Django(状态)部分
迁移的一部分。
- 修改模型文件中的字段。
正常创建迁移。你最终会得到类似的东西:
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)),
),
]
现手动修改为:
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)
]
请注意,您没有指定任何 database_operations
参数,因此修改了 Django 关系,但数据库数据未更改。
不用说:在尝试此操作之前先进行备份。
这就是我设法做到的,它基于 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
)
]
从 Django 2.0 开始,将您的字段更改为 models.ForeignKey(db_constraint=False, db_index=False, ...)
将生成执行 ALTER TABLE DROP CONSTRAINT 和 DROP INDEX IF EXISTS 的迁移,这似乎正是您想要的。
我有一个 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,如果是这样,我如何以编程方式获得约束名称?
参见 SeparateDatabaseAndState。它允许您从数据库中单独指定迁移的 Django(状态)部分 迁移的一部分。
- 修改模型文件中的字段。
正常创建迁移。你最终会得到类似的东西:
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)), ), ]
现手动修改为:
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) ]
请注意,您没有指定任何 database_operations
参数,因此修改了 Django 关系,但数据库数据未更改。
不用说:在尝试此操作之前先进行备份。
这就是我设法做到的,它基于 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
)
]
从 Django 2.0 开始,将您的字段更改为 models.ForeignKey(db_constraint=False, db_index=False, ...)
将生成执行 ALTER TABLE DROP CONSTRAINT 和 DROP INDEX IF EXISTS 的迁移,这似乎正是您想要的。