Django 1.7 migrations won't recreate a dropped table, why?

前端 未结 10 1036
挽巷
挽巷 2020-12-23 14:16

Using Django 1.7 migrations.

I accidentally dropped a table in my database. I assumed that by running migration again this would recreate the table but no, Django st

相关标签:
10条回答
  • 2020-12-23 14:28

    Just ran into this while building a little app learning django. I wanted to create a non-null column for an existing table. There were three steps:

    1. drop the table
    2. remove the record in django_migrations
    3. remove the migration for the table in question
      • if you run "python manage.py makemigrations posts" before this step you still get the "You are trying to add a non-nullable field "

    For an actual application you'd need to supply a default value as others have pointed out.

    0 讨论(0)
  • 2020-12-23 14:29

    Full disclaimer, this is a destructive operation in some cases, and I mostly use it to remigrate parts of the system without affecting the DB.

    Have you tried doing it via the table django_migrations? Just remove the rows that map to the app label and the migration names in question and delete those rows.

    +----+-----------------------+----------------------------------------------------------+---------------------+
    | id | app                   | name                                                     | applied             |
    +----+-----------------------+----------------------------------------------------------+---------------------+
    |  1 | contenttypes          | 0001_initial                                             | 2015-03-07 16:32    |
    | 30 | homepage              | 0001_initial                                             | 2015-04-02 13:30:44 |
    | 31 | homepage              | 0002_auto_20150408_1751                                  | 2015-04-08 12:24:55 |
    | 32 | homepage              | 0003_remove_mappinghomepagemoduleinventory_inventoryinfo | 2015-04-09 08:09:59 |
    +----+-----------------------+----------------------------------------------------------+---------------------+
    

    So now if i want to remove homepage, I can just delete row 30, 31, 32.

    Of course since you dropped the tables too, you'd need to change django_content_type too:

    +----+----------------------------------------+-----------------------+--------------------------------------+
    | id | name                                   | app_label             | model                                |
    +----+----------------------------------------+-----------------------+--------------------------------------+
    |  1 | content type                           | contenttypes          | contenttype                          |
    |  2 | session                                | sessions              | session                              |
    |  3 | site                                   | sites                 | site                                 |
    | 92 | master_homepagemodule_extrafields      | homepage              | masterhomepagemoduleextrafields      |
    | 93 | mapping_homepagemodule_inventory       | homepage              | mappinghomepagemoduleinventory       |
    | 94 | master_homepagemodule_inventoryfields  | homepage              | masterhomepagemoduleinventoryfields  |
    | 95 | mapping_homepagemodule_inventoryfields | homepage              | mappinghomepagemoduleinventoryfields |
    | 96 | master_homepagemodule                  | homepage              | masterhomepagemodule                 |
    | 97 | mapping_homepagemodule_extrafields     | homepage              | mappinghomepagemoduleextrafields     |
    +----+----------------------------------------+-----------------------+--------------------------------------+
    

    So now you'd have to remove the tables that you need to remigrate need by dropping the rows for those tables.

    I've used this when time was scarce and we needed a quick dirty fix, or when playing around in development.
    Hope it helps you too!

    0 讨论(0)
  • 2020-12-23 14:29

    OK, so what I did was not to mess with migrations. Seems like I get in trouble every so often with migrations. And in this case, trying to replay migrations got me nowhere. Might not have helped that there were some South-vintage migrations as well as the newer 1.7 stuff.

    environment: postgres 9.3

    Basically, I restored an old backup of my database into an empty database. Then I brought up the restore target in the postgres admin utility and copy/pasted the create tables from each table's description (I had only 4 to go). Switched over to my test database & ran it in pg's sql utility.

    I dunno, I don't think it is unreasonable to drop a table manually if you are having issues with it (looked to me as if my id field's sequence was not working), as long as you can live with losing your data. Migrations should be resilient in that use case.

    0 讨论(0)
  • 2020-12-23 14:33

    I actually found an easier way to do this. You fake that you rollback what doesn't exist, then you re-migrate. If your migration 0005 was the one where it creates the table:

    python manage.py migrate myapp --fake 0004
    python manage.py migrate myapp
    

    Should be good after that!

    If you need to skip later ones, you do this:

    python manage.py migrate myapp --fake 0004
    python manage.py migrate myapp 0005
    python manage.py migrate myapp --fake
    

    Should be good after that!

    0 讨论(0)
  • 2020-12-23 14:34

    The simplest way to do this on django >= 1.9 is to run the following:

    ./manage.py migrate app_name zero
    

    That will remove your tables and revert all migrations.

    0 讨论(0)
  • 2020-12-23 14:43

    Probably the simplest way to do it.

    1. Make a copy of the migration file that you want to migrate and rename it as the latest migration file

    e.g. if the file you want to migrate is app_name.002_xyz, and your latest migration file is app_name.004_abc

    Then you need to make a copy of app_name.002_xyz and rename it as the latest migration file. For example, let's rename it to app_name.005_xyz

    1. Now add the recent latest as a dependency in this new file

    e.g. add this line to the new migration file

    class Migration(migrations.Migration):
    
        dependencies = [
            ('app_name', 'app_name.004_abc'),
        ]
        
        ...
    
    1. Migrate it

    e.g. add this line to the new migration file

    python manage.py migrate app_name
    
    1. Awesome, the new migrations are made and tables are recreated

    e.g.

    Running migrations:
    Applying app_name.005_xyz...OK
    
    1. Delete the new migration file app_name.005_xyz and you're good!
    0 讨论(0)
提交回复
热议问题