4

I'm building a project using django v2.0.2 that consists of 3 apps with 24 models. One of the apps has 14 models. Having so many models in one app is becoming complicated, and I'd like to create a new app and move few models to this app.

I found an answer explaining how this can be done using south. I've been using django core migrations and since south is deprecated, I don't want to switch to south at this point.

The models I want to move are quite complex - they have ForeignKey fields, ManyToMany fields, etc. I need a workflow showing how I can move these models using django core migrations.

rahul
  • 306
  • 4
  • 19

1 Answers1

5

That shouldn't be too difficult to do. The main issue you run into is that Django automatically derives the name of the database table from the name of your model class and the app that contains it.

That means unless you're explicitly setting the db_table property in the model meta, the names of all the tables corresponding to your models are auto generated based on app/model name combo.

So if you have a Post model in a Blog app, the auto generated table name of that Post model is blog_post. And if you decide to move Post model to the Article app, Django will be looking for a table named article_post and won't be able to associate your model with the correct table.

To solve this issue, you need to explicitly set the db_table property on each of the models. The db_table name value will have to correspond to the current app/model combo. So in the case of Post model mentioned above, you would set db_table to blog_post. Once you set the db_table property, you can move the model to any other apps.

class Post(models.Model):
    title = models.CharField(max_length=120)

    class Meta:
        db_table = 'blog_post'

Once you move all the models around, login to django admin to verify that your data is still accessible through the newly moved models.

When you run makemigrations for the first time after moving the models, Django migrations will create migration files that deletes the moved models in their old app and recreate them in their new app. Do not apply these migrations and instead run migrate --fake which will record the migrations as having been executed without making any of the database changes. After that, your migration files and your database structure will be synced.

AdonisN
  • 480
  • 4
  • 12
  • A bit of a problem here. Moving the models to a new app, modifying these models and running a migration is deleting the db tables from the old app and creating new ones in the new app. Why would this happen? We've already linked the models in the new app to the old db tables.. – rahul Feb 19 '18 at 16:33
  • 1
    run migrate --fake and that will record the migrations as having been executed without making any of the database changes. After that, your migration files and your database structure will be synced. I'll update the response. – AdonisN Feb 19 '18 at 17:52
  • 2
    Sometimes you cannot fake migration (e.g. CD pipeline applying migrations and tests). In this case take a look into generated migration file and remove unnecessary steps. But I would prefer migrating data using RunPython to new models. – pista329 Jan 08 '19 at 19:03