initial migrations는 앱의 테이블의 첫 번째 버전을 생성하는 것을 뜻한다. 가끔 복잡한 모델의 경우 2개 이상의 initial migrations를 갖기도 한다.
initial migrations는 Migration 클래스 내에 initial = True
속성으로 표시된다. 만약 이 속성이 없는데 첫 번째 마이그레이션에 해당하는 경우 해당 마이그레이션은 initial migrations로 간주 된다.
--fake-initial 옵션을 추가하면 initial migrations는 조금 특별하게 취급된다.
--fake-initial
옵션에 의해 fake-applies를 하게 된다. 만약 사용자가 만든 앱에 이미 모델과 데이터베이스 테이블은 있지만 migrations는 없는 상황이라고 가정해 보자. 그러면 아래 명령어를 통해 해당 앱이 마이그레이션을 사용하도록 만들 수 있다.
$ python manage.py makemigrations your_app_label
이렇게 initial migration을 생성하고 나면 일반적으로 테이블이 없는 경우 python manage.py migrate
를 실행하지만 지금처럼 테이블이 이미 생성되어 있는 상태인 경우 python manage.py migrate --fake-initial
를 실행하면 된다.
이 명령어를 실행하면 장고는 이 앱이 이미 initial migration과그에 해당하는 테이블을 이미 가진 상태이며 migration이 이미 적용되었다고 마크해 놓을 것이다. 즉, 테이블이 실제 생성되지는 않았지만 장고가 알아서 migrate이 되었다고 표시해 준다는 것이다.
migrate를 할 때는 아래 두 가지를 주의해야 한다.
migratioin 의존성을 수정할 때 가끔씩 migration은 적용 되어 있지만 이의 dependencies는 적용되지 않은 일관적이지 않은 상태가 될 때가 있다.
이는 곧 dependencies가 바르게 설정 되지 않았다는 것을 뜻하며 이에 따라 장고는 해당 사항이 수정될 때까지 migration을 실행하거나 만들기를 거부하게 된다.
이 때 만약 여러 개의 데이터베이스를 사용하는 경우(default, custom 등등) allow_migrate()
설정을 사용해 migration을 실행시킬 수 있다. makemigrations 실행하도록 함으로써 일관된 history를 만들 수 있다.
만약 현재 books 앱에 0003까지 migration이 적용되어 있다고 해보자.
이전 마이그레이션으로 되돌리고 싶다면 0002로 migrate를 하면 된다.
그런데 만약 books 앱의 모든 마이그레이션을 되돌리고 싶다면 아래 명령어를 실행하면 된다.
$ python manage.py migrate books zero
Operations to perform:
Unapply all migrations: books
Running migrations:
Rendering model states... DONE
Unapplying books.0002_auto... OK
Unapplying books.0001_initial... OK
하지만 되돌릴 수 없는 migration도 있다. 이 경우 migration을 되돌리려 하면 IrreversibleError
가 발생한다.
$ python manage.py migrate books 0002
Operations to perform:
Target specific migration: 0002_auto, from books
Running migrations:
Rendering model states... DONE
Unapplying books.0003_auto...Traceback (most recent call last):
django.db.migrations.exceptions.IrreversibleError: Operation <RunSQL sql='DROP TABLE demo_books'> in books.0003_auto is not reversible
migrations로 managers를 필요에 의해 직렬화(serialize)할 수 있다.
이를 위해서는 Manager class에 use_in_migrations
를 정의하면 된다(boolean이다).
class MyManager(models.Manager):
use_in_migrations = True
class MyModel(models.Model):
objects = MyManager()
직렬화란?
여기에 잘 설명 되어 있다.