Using Django South to move from concrete inheritance to abstract inheritance

前端 未结 2 555
抹茶落季
抹茶落季 2021-01-11 18:34

I have an existing Django project that has several models using concrete inheritance of a base class. After closer consideration, and after reading about what people like Ja

相关标签:
2条回答
  • 2021-01-11 19:08
    1. Add NewBaseModel, we use different name so it doesn't conflict with current non-abstract one (South would actually delete BaseModel otherwise).

      class NewBaseModel(models.Model):
          user = models.ForeignKey(User)
          another_field = models.CharField(max_length=1000)
      
          class Meta:
              abstract = True
      
    2. Set Model1 and Model2 to inherit from NewBaseModel

    3. Run schemamigration --auto, 2 new fields will be added to Model1 and Model2
    4. Run datamigration --empty and fill new fields from values in BaseModel
    5. Load production db and double check everything migrated correctly
    6. Remove BaseModel and rename NewBaseModel to BaseModel
    7. Run schemamigration --auto (this should work ;) )
    8. Deploy!

    NOTE: Use orm variable when migrating to use current state of your model schema.

    0 讨论(0)
  • 2021-01-11 19:10

    Sebastjan Trepča's answer is probably good but, another way to do it will be to create your migration manually:

    1. Add the abstract = True to your base model.

    2. Run schemamigration --auto, the generated migration will probably not be good but you will use it as a base.

    3. Edit the migration file. In the forward you should add, in this order:

      a. db.delete_foreign_key(table_name, column) for each of your children models. This will remove the ForeignKey between the parent and the children table.

      b. db.delete_table(BaseModel) to delete the table of the base model (this command should be probably there already, generated by --auto).

      c. It's possible that you will have to rename all the primary key column of your children models to 'id'. I'm not sure about this. If you need to do this: db.rename_column(table_name, column_name, 'id') for each of your children models.

    4. Remove all auto-generated code in forward that doesn't make sense.

    5. Run the migration: migrate

    What this method is doing is removing the table of the base class and the foreign keys between the base class table and its children because they are not use with the Abstract Base Class.

    I didn't test this method so it's possible that you'll hit some problems. This approach is more complicated then the other one but the advantages are that you don't need to migrate the data and that you will understand what is happening. It should run also pretty fast, a good thing for a live migration.

    You can consult the South API for more info.

    One really important thing, in any method you will use, work on a local copy of your system and database. When you will be really sure that the migration is working well, backup your production DB then apply your migration and then restart your webserver (to load your modified model code).

    0 讨论(0)
提交回复
热议问题