0

I want to rename a model in Django 3.2, keep my existing migrations and be able to both migrate a db with the old table name and create a db from scratch.

I've started by renaming the model class and all references to it in the code. As "./manage.py makemigrations" did not automatically create a migration, I manually created a migration that renames the model:

from django.db import migrations

class Migration(migrations.Migration):

    dependencies = [
        ('market_integrations', '0003_migration'),
    ]

    operations = [
        migrations.RenameModel('OldModelName', 'NewModelname')
    ]

My initial idea is that I should not update existing migrations, as I never do when creating other migrations. However, the references to the old model in the old migrations cause a LookupError when I run "./manage.py migrate". I've tried using both the model name string and apps.get_model(). Migration code samples that break:

operations = [
    migrations.CreateModel(
        name="OldModelName",
    ...
    )
]


operations = [
    migrations.CreateModel(
        name=apps.get_model("myapp", "OldModelName"),
    ...
    )
]

As keeping the old model name in old migrations didn't work, I replaced the old model name in old migrations with the new name. After doing that, "./manage.py migrate" ran successfully, including the model renaming migration. However, when I try to create a new database, the model renaming migration fails because that new database never had a table with the old name.

What should I do to be able to preserve my migrations and have them working in both existing and new databases?

I have already checked Django migration strategy for renaming a model and relationship fields , but I didn't find the answer to my question there.

Alan Evangelista
  • 2,888
  • 6
  • 35
  • 45

1 Answers1

0

Please attach the full model (you can delete irrelevant fields) and the migration you created in your initial question (I cannot comment on your initial post yet, so I have to mention it in an answer).

This is important because I think there are foreign keys pointing to the model you want to rename. Or are you trying to rename Foo to Bar and create a new Foo?

Does the error also occur if you try to start the server after your initial idea? Your initial idea of keeping existing migrations untouched seems good, because you will be able to run it on all your environments (local, dev, prod, etc), and approach 2 would require manual renaming of database tables and fields.

I might be able to extend my answer after you provide models and migrations.

    migrations.RenameModel(
        old_name="ModelA",
        new_name="ModelB",
    ),

    migrations.AlterField(
        model_name="myrelatedmodel",
        name="somefieldname",
        field=models.ForeignKey(
            # change the properties accordingly (best copy it over). The database may only change to="table"
            null=True,
            on_delete=django.db.models.deletion.SET_NULL,
            to="myapp.modelb",
        ),
    ),

If this did not work, where does the error come from? You can try to isolate your migrations and models from the rest of the code (like in a new empty project attached to the same database). Maybe this will help you find out if the error is from a leftover reference to OldModelName or some weird error. Just as an idea so you don't spend time looking at the wrong place

Try to do one change and one migration at a time. You can later squash them. If django does not auto-detect the renaming of your model, it means that all fields related to this model will fail too.

  1. Revert everything to the working state before renaming
  2. Make sure all migrations are applied
  3. Rename the model and create a migration to only rename the model. Are you able to apply it?
  4. if not, try to manually modify all related fields (one2one, foreignkey, etc)

If that still fails, create a copy of your model in models.py, rename the copied model and try to use migrations.RunPython() in a new migration file to copy all the data from the old table to the new one.

If you only have one populated database, you might get away with replacing all ModelA occurrences with ModelB and change the structure of your database.

Best of luck!

nOperator
  • 111
  • 1
  • 4