Django에서 migrations error 발생할 때 migration 초기화하기
이 문서는 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
-
DB 스키마가 올바르고 migrations 기록만 잘못된 경우
django_migrations
테이블을 수동으로 편집하여 이 문제를 해결할 수 있다. -
만약 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를 직접 수정하여 해결하였습니다. 끝!