Opened 5 years ago

Closed 5 years ago

Last modified 5 years ago

#30869 closed New feature (wontfix)

Setting to confirm destructive/weird migrations.

Reported by: awiebe Owned by: nobody
Component: Migrations Version: dev
Severity: Normal Keywords: destructive, setting
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

If altering or deleting a column could result in loss of data the migrate command should inform you, unless you have set a flag in the migration file that says you have provided an appropriate data migration.

When iterating, on non production code it's obviously fine if data is added and removed because you're just using test data anyway, but migrations make their way into production code, and then suddenly the fact that you deleted a column as part of an intermediate migration matters, even if you provided a replacement at some later point. I would put a setting that prevents django from executing:

  • Delete Model
  • Remove Field
  • Alter Field

Without a review of the migration. This could be a setting but maybe it should always be on.

If possible it would also be helpful if django would automatically split destructive operations and non destructive operations into two steps. For example.

If I add a column that will contain the migrated data, and remove the column that held the old data, the operation to create and populate the new column needs to happen first. I don't know if the migrator already handles this but iff not, then destructive operation should be pushed into a separate subsequent migration, where the "data migration provided" flag is already set.

I had this problem when I was trying to change a string field to a foreign key, and the migrator just turned my sqlite column from a string column to an integer, which is perfectly legal in sqlite for some reason. But didn't actually I should have made a data migration that I didn't notice.

This was on a test database, but I essentially had to unpick weird things sqlite did, which could have been avoided if django had been a bit more conservative about migrating.

Change History (2)

comment:1 by Mariusz Felisiak, 5 years ago

Resolution: wontfix
Status: newclosed
Version: 2.2master

Thanks for this report, however I don't think that we should force users to confirm that they really want to delete a model or remove a field because that causes a data loss. It seems quite clear to me that when you remove a table or column, you'll will lose data. IMO it's not Django job to explain that.

About fields altering, DB should prevent you from losing data (it is not possible to change a text-type field into a number-type field in most databases). SQLite limitation is already described in documentation.

comment:2 by Simon Charette, 5 years ago

FWIW you could implement a confirmation mechanism by connecting a receiver to the pre_migrate signal based on the interactive flag.

e.g.

def confirm_destructive_operation(plan, interactive, **kwargs):
    if not interactive:
        return
    for migration, backward in plan:
       if backward:
          return
       for operation in migration.operations:
           if isinstance(operation, RemoveField):
               if not confirm("You're about to remove field..."):
                   break

It should be straightforward to implement as a third party package.

Note: See TracTickets for help on using tickets.
Back to Top