Django 1.9 drop foreign key in migration

旧街凉风 提交于 2019-11-30 15:19:53

问题


I have a Django model that has a foreign key to another model:

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

I want to keep the underlying DB column as a field, but to get rid of the foreign key constraint in the database.

So the model will change to:

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

And, to be clear, something_id is the column that Django had created for the foreign key field.

I do not want to drop the column and re-create it (this is what Django does when I auto-generate migrations after changing the model as above).

I want to keep the field but I want to remove the foreign key constraint in the database with a migration. It's not clear to me how to do this with a Django migration - is there some built in support for it or do I have to run some raw SQL and, if so, how do I programatically get the name of the constraint?


回答1:


This is how I managed to do it, it's based on nimasmi's answer above:

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



回答2:


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.




回答3:


As of Django 2.0, changing your field to models.ForeignKey(db_constraint=False, db_index=False, ...) will generate a migration that does ALTER TABLE DROP CONSTRAINT and DROP INDEX IF EXISTS, which appears to be exactly what you want.



来源:https://stackoverflow.com/questions/38311503/django-1-9-drop-foreign-key-in-migration

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!