Intro
Django
로 개발을 하면서 자주 TABLE
( 혹은 Model
, 섞어서 표현하겠음. )을 삭제할 때 Migration
에 대한 개념이 별로 없어서인지 django.db.utils.OperationalError: no such table
에러를 자주 만나게되었습니다.
이번에도 한 번 그런 에러가 발생해서 이번 기회에 한 번 정확한 해결방법 및 Django
에서 Model
을 삭제하는 방법에 대해 정리해보려합니다.
요점
중요한 점은 django ORM
(Database
를 직접 다루는 게 아니라 Django
에서 api
를 통해 다루는 방식 ) 에서
python manage.py makemigrtions
는 DB에 migrate할 변동내역을 적어놓기만하는 것이고
실제 DB에 그 내용이 반영되는 것은
python manage.py migrate
를 통해서만! 입니다.
migration
에 대한 좀 더 자세한 내용은 초보몽키 블로그 에 나와있는데, 궁금하시면 참고해보세요.
변동사항들이 적힌 migration files를 통해 롤백할 앞 뒤로 롤백할 수도 있습니다. 따라서 간혹 migration files를 통째로 지워서 TABLE
을 지워버리는 경우도 있기는 한데, 조심해야할 수도 있다고 하네요. ( 롤백을 못해버리니까? )
django.db.utils.OperationalError: no such table
주로 이 에러는 django ORM
을 통해서가 아니라 DB shell
을 통해 직접 TABLE
을 삭제할 경우 발생하는 것 같아요. 아직 Model
, 즉 TABLE
을 어떻게 삭제하는 지 몰라서 django
로 뚱땅거리다가 *에라모르겠다; 하고 DB에 가서 직접 DROP TABLE name; * 을 때려버리는 거죠.
그리고 나서 이제 makemigations 를 하면 - Delete Model ...
이라며 성공적인 문구를 발견하고 기분이 넘 좋아질 수 있지만, 그것도 잠시 migrate를 하면 다시 django.db.utils.OperationalError: no such table
에러가 발생합니다.
원인
migrate
는 기본적으로 자신이 가장 마지막으로 migrate한 이후의 migration file 부터 migrate를 진행합니다. 변동사항을 DB에 적용한다는 거죠. 근데 DROP TABLE은 내가 이미 직접 진행했죠.
하지만 이후 models.py에서도 model을 주석처리하든 없애든 했으니 migration file에는 해당 TABLE을 지우라는 migration file을 만듭니다.
그리고나서 migrate 하려는데 지우라는 TABLE이 이미 지워져있으니 지울 게 없어서 no such table
에러가 발생하는 거죠.
해결방법
TABLE을 삭제하려는데 django.db.utils.OperationalError: no such table 오류가 난 경우
-
models.py
에서 삭제할 model의 코드를 없애고python manage.py makemigrations
를 통해 migration file을 만든다.No changes Detected
가 떠도 괜찮다. 보통은Delete model ...
가 뜰 것이다. -
python manage.py migrate --fake
를 입력한다.이게 뭐냐면 변동사항이 적힌 migration을 진행한 척 하는 겁니다. 쉽게 말해서 나중에 실행해야할 migraion file index를 건너뛰는 느낌. 실행하지 않았지만, index는 진행시키는 느낌.
-
이후에 자유롭게 원하는 작업 하시면 됨.
작업의 순서가 중요! migrate --fake
는 그 동안 만들어진 migrations file을 뛰어넘는 것이기 때문에 migrate 를 입력한 뒤 migrate --fake
를 입력한다거나 하면 아무 효과가 없기 떄문에, 위의 순서를 지켜주는 것이 중요합니다.
너무 다양한 케이스가 있어서 자세히 적기는 힘드네요. 거의 시뮬레이션 급이라.
Django 에서 Model을 삭제하는 가장 좋은 방법
가장 좋은 방법은 아무래도 Django ORM
그대로를 이용하는 것입니다. 다만 Django 에서 삭제되는 TABLE에 대한 Backup은 지원하지 않으니 필요한 경우 알아서 백업해야합니다.
-
models.py
에서 삭제할 model의 코드를 주석처리한다. (나중에 오류났을 때 다시 써야하는 경우도 있어서 지우는 것 보다는 주석이 나음) -
admin.py
및 다른models.py
등등에서ForeignKey
나ManyToMany
로 지우려는 model을 참조하는 경우를 다 지운다. -
python manage.py makemigrations
입력!`- Delete talbe ...` 이 떠야함
-
python manage.py migrate
로 migrtaion file의 내용 DB에 반영.
예시
아래와 같은 models.py
에서 직접 DROP TABLE
을 하고 ( 예시에서는 SQLite3
를 이용함. ) models.py
에서 model 코드를 주석처리하면 DBShell에서 TABLE
이 삭제되고, makemigrations
까지는 성공적이지만 migrate
는 에러가 발생함.
따라서 python manage.py migrate --fake
를 입력해주면 내가 이미 migration에 적힌 변동내역을 직접 진행했었고, 따라서 migrtaion에 적인 내용을 python manage.py migrate
에서는 fake로 실행하여 오류가 발생하지 않고 다음의 어떤 작업이든 수행할 수 있습니다.
이제 테이블을 성공적으로 삭제했고, 내용을 반영했으니, 이후에 다른 작업을 원활히 수행할 수 있나 보겠습니다.
다시 School Model을 생성하고 makemigrations, migrate를 진행하였더니 문제없이 잘 작동하네요.
배운 점
TABLE을 지우는 것은 쉽지 않은 일입니다. 특히나 Schema가 복잡해질 수록, 한 테이블을 잘못 지웠다가는 의존성과 CASCADE에 의해 주루룩 테이블들이 다 지워질 수도 있을 것 같은데, 이번에 좀 명확히 어떻게 TABLE을 지우는 지 알게 된 것 같아 다행입니다.
잘못 지우는 작업을 수행한 Schema는 다시 복구하기도 힘들 수도 있습니다..
가장 좋은 것은 django 에서의 migration에 대한 의미를 정확하게 알게되어 다행이네요.
'Python > Frameworks.Libraries' 카테고리의 다른 글
docker-compose를 통해 Nginx, Django 연동하기 2 - Django App과 uWSGI 연동하기 (0) | 2019.09.08 |
---|---|
Django App Templates Directory. 장고 앱 템플릿 디렉토리 구조에 대해 (0) | 2019.09.02 |
docker-compose를 통해 Nginx, Django 연동하기 1 - 간단한 Django app 만들기 (0) | 2019.07.22 |
웹서버를 짜주는 Django 에서 프로젝트를 구성하는 방식 (0) | 2019.06.29 |
[파이썬 게임 예제] pygame으로 벽돌깨기 만들기 (0) | 2019.02.23 |