26

I want to know if any one could give a complete list of things which need to be done when we want to remove a model from Django. I know that a similar question was asked. But it seems to be several years ago, when people were still using South to deal with Database. So I expect an answer for the recent version of Django.

I conclude what I know as follows:

  1. Delete the codes for model from model.py
  2. Make sure that no other file imports this model or uses them (admin.py, views.py, etc)
  3. Run makemigrations and migrate commands
  4. Since Django doesn't clean database for you, you delete the table of this model manually from you database
  5. Also note that there is a table called ContentTypes, which keeps records about the info our your every model. So you need to delete the record for this model manually (But I don't know how to do it exactly. Would any one give some explanation?)

These are all the things I know. Is there anything wrong? And did I forget anything? Maybe I'm over-cautious, but I'd like to keep the database clean. Thanks a lot!

Xiao Liang
  • 763
  • 2
  • 7
  • 12
  • 2
    You may run into issues where migrations have dependencies on the now non-existent model. I'm running into this myself, and haven't found a good solution yet. I'm interested to see what responses you'll get. – Brandon Taylor Mar 14 '15 at 00:57
  • @Brandon, what do you mean by "dependencies on the now non-existent model"? You mean because of there is some other model having a Foreignkey Relation (just for example) with the one you want to delete, so you can't complete the deletion? – Xiao Liang Mar 14 '15 at 02:56
  • Yes, that's correct. – Brandon Taylor Mar 14 '15 at 02:57
  • I'm new to django, so I don't know the right solution. Here is my guess: we can put this problem into two cases. (1) the Foreignkey field can't be Null. (2) It can be Null. If it's case (1), maybe we can delete this model with the model we are trying to delete. Because Foreignkey's non-Null property implies that this model can't exist independently from the model we want to delete. For example, if we delete the model of Books, there is no reason for us to keep the Reviews related to specific book(as all the books are now non-existent). – Xiao Liang Mar 14 '15 at 03:34
  • If it’s case (2), it will be easier. Just delete the ForeignkeyField in the model having dependencies with the model we want to delete firstly, and then we can delete the model we are trying to delete. Does this make sense? – Xiao Liang Mar 14 '15 at 03:35
  • related: https://stackoverflow.com/q/8597322 – djvg Apr 15 '21 at 08:57

1 Answers1

41

In Django 1.7, this is actually much simpler than you think. Let's say you have an app, books, with two models: Book and BookReview. You want to remove the Book model.

  1. Remove all references to the Book model in your code. For example, remove the ForeignKey('books.Book') field on the BookReview model. There is no need to make a separate migration for this change.
  2. Remove the code for the Book model from books/models.py. Now, create a migration (manage.py makemigrations). If you look at the migration that is generated, it should include a migrations.DeleteModel operation.
  3. Run the auto-generated migration (manage.py migrate), and you should be asked about the relevant ContentType objects that are no longer needed:

    Running migrations:
      Applying books.0002_auto_20150314_0604... OK
    The following content types are stale and need to be deleted:
    
        books | book
    
    Any objects related to these content types by a foreign key will also
    be deleted. Are you sure you want to delete these content types?
    

    You probably do want to delete the content types. If you don't want to be asked for input, you can use manage.py migrate --noinput.

    The DeleteModel operation in this migration will drop the books_book table in your database, so you don't have to worry about manually cleaning up at all.

Daniel Hawkins
  • 1,165
  • 13
  • 12
  • 5
    Note that it's perfectly fine to delete the foreign key and the model in the same migration - Django will automatically detect and reorder the migrations to remove the foreign key before the model is deleted. Test case: https://github.com/django/django/blob/1.7/tests/migrations/test_autodetector.py#L684 – knbk Mar 14 '15 at 10:38
  • Oh, thank you. I didn't know that the "DeleteModel" operation in this migration file can do the table-dropping job for me. Maybe that's because the materials I found are kind of out-of-date. So now in Django 1.7+, we need not run any SQL codes in our database and the "manage.py migrate" will have all the things done for us, right? – Xiao Liang Mar 14 '15 at 15:43
  • Good point, knbk -- I've edited the answer accordingly. Xiao Liang, correct, you shouldn't need to run any SQL commands. The migration will do everything for you. :) – Daniel Hawkins Mar 14 '15 at 19:46
  • @knbk, according to the codes in this answer, it says 'Any objects related to these content types by a foreign key will also be deleted'. So it seems to delete the 'object', not only the Foreignkey field of that object, given that we use Django's automatically detecting functionality. Is it true? – Xiao Liang Mar 15 '15 at 00:18
  • @XiaoLiang It will only affect model instances that have a foreign key to the `ContentType` model instance that is deleted, i.e. models that have a `GenericForeignKey` to the deleted model. You can avoid this with a [data migration](https://docs.djangoproject.com/en/1.7/topics/migrations/#data-migrations) that removes/repoints those specific foreign keys before you delete the model. If you don't have a `ForeignKey` to `ContentType`, or it never points to the content type of the deleted model, you have nothing to worry about. – knbk Mar 15 '15 at 00:26
  • Alternatively, don't delete the content type. You wouldn't be able to use any `GenericForeignKey` to the now deleted model, but you're also guaranteed to not lose any data except for the deleted fields/models. – knbk Mar 15 '15 at 00:27
  • @knbk, thanks a lot for your patience. You've made it very clear to me! Thank U~ – Xiao Liang Mar 15 '15 at 04:28
  • What would happen to historical migrations if after this I remove the whole app? – gdvalderrama Mar 04 '21 at 12:10