Home Science Coding Design Etc. AboutMe

Django에서 migrations error 발생할 때 migration 초기화하기

April 7, 2020   /   4 mins read   /  

이 문서는 Stack overflow의 'django.db.migrations.exceptions.InconsistentMigrationHistory'와 Simpleisbetterthancomplex의 'How to Reset Migrations'의 내용을 참고했습니다.


우선 Django의 migrations 시스템을 잘 사용하고있으면 커밋 된 이후로는 데이터베이스를 지우거나 migrations을 지우지 마세요.

(하지만 지웠으니 에러가 떠서 왔겠죠...)

Migrations error를 해결하는 법

우선 DB를 날려도 되는 경우 (완전 초기)와 DB를 보존해야 하는 경우 2가지로 나뉩니다.

1. DB를 날려도 되는 경우

모든 migrations을 삭제하고 python -m manage.py makemigrations

Console

$ python -m manage.py makemigrations

migrations에서 의존성(dependency)이나 불일치(inconsistency)가 없어야 합니다. 모든 전체 DB를 제거하고, (이 경우 DB를 통째로 날리는 것이므로 InconsistentMigrationsHistory error 같은 문제도 자동적으로 해결된다.) 이 후 python -m manage migrate를 통해 DB를 재생성한다.

Console

$ python -m manage.py migrate


2. DB를 날리면 안되는 경우

Inconsistencies with migrations files

함께 작업할 때 자주 일어나는 경우이다. makemigrations --merge를 통해 해결하거나, 다른사람의 migrations 이전으로 롤백해서 해결한다.

Console

$ python manage.py makemigrations --merge


Inconsistencies between your schema and your migrations history

(추후 내용 추가 예정. 저는 이 경우 Git을 이용하여 migrations history를 복구하여 해결했습니다.)


Inconsistencies between your migration history and your migrations files

  1. DB 스키마가 올바르고 migrations 기록만 잘못된 경우 django_migrations 테이블을 수동으로 편집하여 이 문제를 해결할 수 있다.

  2. 만약 DB 스키마가 틀린 경우 DB 스키마가 일치하게끔 수동으로 편집해야 한다.



에러 1 - Error: InconsistentMigrationsHistory

저의 경우에는 Category model을 추가하다가 migrations을 초기화 하던 중, 다음과 같은 에러가 발생했습니다.

Console

django.db.migrations.exceptions.InconsistentMigrationHistory: Migration social_django.0001_initial is applied before its dependency auth.0001_initial on database 'default'.

저는 구글 연동을 위해 OAuth를 추가했었는데, 해당 inconsistent error의 문제인 'social_django'을 우선 INSTALLED_APPS에서 커맨드 아웃(#) 시킨 후, 진행하니 에러를 해결할 수 있었습니다.

before setting.py

INSTALLED_APPS = [
...
    'social_django',
...
]

after setting.py

INSTALLED_APPS = [
...
#    'social_django',
...
]



DB를 제거하지 않고 migrations만 초기화 하기

이 과정에서, DB를 제거하지 않고 migrations만 초기화 하려면

showmigrations 명령어로 migrations 현황을 확인한 후,

Console

$ python manage.py showmigrations

Result

admin
 [X] 0001_initial
 [X] 0002_logentry_remove_auto_add
 [X] 0003_logentry_add_action_flag_choices
yourapp
 [X] 0001_initial
auth
 [X] 0001_initial
 [X] 0002_alter_permission_name_max_length

migrations을 초기화 할 앱에 대해서 migrate --fake appname zero를 통해 초기화 할 수 있습니다.

Console

$ python manage.py migrate --fake yourapp zero

제대로 되었는 지 확인하려면 다시 한번 showmigrations을 통해 확인 할 수 있습니다.

Result

admin
 [X] 0001_initial
 [X] 0002_logentry_remove_auto_add
 [X] 0003_logentry_add_action_flag_choices
yourapp
 [ ] 0001_initial
auth
 [X] 0001_initial
 [X] 0002_alter_permission_name_max_length

이 후 실제 migrations 파일들을 삭제합니다. (migrations 폴더에서 __init__.py 파일을 제외한 모든 파일 삭제)

(문제 발생 시 제겐 책임이 없으니, 삭제 할 때는 여러번 꼼꼼히 확인해보시길 바랍니다. )

그러면 showmigrations을 통해 확인했을때 해당 앱이 (no migrations) 상태로 변경됩니다.

Console

admin
 [X] 0001_initial
 [X] 0002_logentry_remove_auto_add
 [X] 0003_logentry_add_action_flag_choices
yourapp
 (no migrations)
auth
 [X] 0001_initial
 [X] 0002_alter_permission_name_max_length

다음으로 첫 migrations을 생성하고, 이미 DB가 존재하므로 (삭제하지 않았으므로) 가짜로 migrate 시켜줍니다.

Console

$ python manage.py makemigrations
$ python manage.py migrate --fake-initial



에러 2 - Error: Index "~~" already exists

그런데 migrate 하려니, 다음과 같은 에러가 떴습니다.

Console

django.db.utils.OperationalError: index taggit_taggeditem_content_type_id_object_id_196cc965_idx already exists

기존에 추가해두었던 taggit app에서 migrations 된 index가 이미 있다. 라고 에러를 뱉어냈어요. 그래서 또 해결책을 찾아보니, DB를 직접 수정하면 될 것으로 판단, manage.py dbshell을 쳤는데, 이번에는

Console

CommandError: You appear not to have the 'sqlite3' program installed or on your path.

sqlite3로 db를 못 읽어서 (아마도 sqlite3의 경로가 제대로 지정이 안되어 실행을 못 한듯?, 추후 확인 필요) 에러가 발생했습니다. PATH를 설정하면 된다는데, 사실 DB툴은 잘 써보질 않아 어려워서 편하게 볼 수 있는 프로그램을 깔기로 했습니다.

프로그램은 DB Browser for SQLite를 사용 했습니다. (공식 홈페이지: https://sqlitebrowser.org/dl/)

이 후 DB를 직접 수정하여 해결하였습니다. 끝!