10

I have a Model named FooModel defined in a my_app/models/foo.py.

After deleting foo.py, running Django (1.7) migrations raises an error since the old migration files import foo.py (import myapp.models.foo.FooModel).

How should I resolve this?

This happens when the model has an ImageField with an upload_to parameter.

aumo
  • 5,344
  • 22
  • 25
eugene
  • 39,839
  • 68
  • 255
  • 489

2 Answers2

9

There are two cases:

  1. You moved FooModel elsewhere, then edit all your migration files to reflect that move.

  2. You removed FooModel, in this case, follow these steps:

    • Put FooModel back to where it was.
    • Make sure there are no references to FooModel elsewhere in your code.
    • Run ./manage.py makemigrations my_app
    • Run ./manage.py squashmigrations my_app <migration created with the previous comand> — see the doc for more informations on squashing migrations.
    • Repeat the two previous steps for any app that references FooModel in its migrations.
    • Remove FooModel and the stale migration files once you ensured everything worked fine.

This should work because as FooModel is not referenced from any other model, it should be removed from the migrations files when squashing them.

However, be warned that squashing migrations is not a simple operation and may have consequences it might be a better idea to just keep the model in your codebase without using it.

Note: in this situation, the object in question is a Django model but this applies to any class, function or module referenced by migration files.

aumo
  • 5,344
  • 22
  • 25
  • Thanks! hoped there would be an easy solution. But good to know the best option available at the moment as well. – eugene Apr 30 '15 at 13:32
  • Oh wow, thank you! I didn't know you can squash migrations. In my case it was even simpler, just squashing the app which migrations referenced the deleted model did the trick. – Alexander Eliseyev Sep 02 '18 at 02:56
0

In custom database migrations you should not import your models directly because you can face this particular issue in the future. Instead you should rather use Djangos get_model function.

MyModel = apps.get_model('myapp', 'MyModel')
for row in MyModel.objects.all():
    row.uuid = uuid.uuid4()
    row.save(update_fields=['uuid'])

In this case the migrations will also run when you decide to delete the model in the future.

Further read: https://docs.djangoproject.com/en/2.2/howto/writing-migrations/

apparat
  • 1,930
  • 2
  • 21
  • 34
  • What about regular classes (not models)? In that case, we can't use `apps.get_model()`. How do you deal with deleted classes imported in migrations in this case? – Kurt Bourbaki Jun 26 '22 at 12:05