장고 마이그레이션
relational, none-relational
릴레이션은 테이블을 뜻한다.
릴레이셔널 데이터베이스는 테이블에 저장하고
논 릴레이셔널 데이터베이스는 방법이 정해져 있진 않고 보통 JSON같은 문서 형태로 저장한다.
문서형태는 데이터 형식을 자유롭게 할 수 있고 정보를 한 문서 안에서 바로 가져올 수 있어 더 빠르다는 장점이 있다.
하지만 데이터가 중복되는 단점이 있다.
릴레이셔널 데이터베이스는 보통 중복을 허용하지 않고 특정 데이터는 한 곳에서만 관리하기 때문에 데이터의 일관성을 보장한다.
그리고 SQL을 사용할 수가 있다.
마이그레이션
마이그레이션은 장고 모델에 정의된 내용을 데이터베이스 테이블로 옮겨주는 과정이다.
python manage.py makemigrations로 마이그레이션 파일을 만든다.
마이그레이션을 모두 적용했을 때의 모델 상태와 현재 모델 상태의 변경점을 기록한다.
python manage.py migrate로 데이터베이스에 적용을 한다.
마이그레이션 파일을 sql로 변환 후 실행해 데이터베이스에 변화를 준다.
마이그레이션 파일로 모델 히스토리를 파악하고 예전 모델 버전으로 되돌릴 수 있다.
마이그레이션은 앱 단위로 관리한다.
-
마이그레이션 확인
python manage.py showmigrations -
특정 앱의 마이그레이션 확인
python manage.py showmigrations [앱 이름] -
특정 앱의 특정 파일의 마이그레이션 적용
python manage.py migrate [앱 이름] [파일 번호] -
특정 앱의 마이그레이션 적용
python manage.py migrate [앱 이름] -
모든 앱의 마이그레이션 적용
python manage.py migrate -
특정 앱만 마이그레이션
python manage.py makemigrations [앱 이름] -
마이그레이션 name옵션
python manage.py makemigrations –name “[이름]”
깃 커밋을 할 때 메세지를 남기는 것 처럼 마이그레이션의 이름을 지정할 수 있다. 지정하지 않을 때에는 장고가 자동으로 이름을 정하지만 의미없는 이름이 생성될 때가 있어 직접 name옵션을 사용해 이름을 지정하는게 좋다.
앞의 숫자는 자동생성된다.
“initial”이라 하면 “0001_initial”이렇게 된다.
db.sqlite3
vscode에서 sqlite viewer익스텐션을 사용하면 파일을 읽을 수 있다.
이전 마이그레이션으로 돌아가기
python manage.py migrate [앱 이름] [돌아갈 파일 번호]
돌아가고 싶은 부분을 작성해 실행하면 돌아갈 수 있다.
돌아가고 나서 마이그레이션 파일은 직접 삭제해준다.
특정 앱의 모든 마이그레이션을 취소하려면
python manage.py migrate [앱 이름] zero
0001번을 취소하려면 0000번으로 가야하는 데 0000번은 없으니 zero를 쓴다.
이 때 취소된 마이그레이션에 의존하는 다른 마이그레이션도 취소된다.
마이그레이션 디펜던시
migration dependency
코드 a가 코드 b에 의존할 때, a는 b에 대한 디펜던시가 있다라고 한다.
다르게 말해서 코드 b없이는 코드a가 작동할 수 없고 b는 a의 디펜던시이다.
migration파일에서
dependencies = [
('auth', '0011_update_proxy_permissions'),
]
해당 파일은 auth앱의 0011번 마이그레이션에 디펜던시가 있는 것이다.
0005번을 마이그레이션 하려면 0005번의 디펜던시를 먼저 모드 마이그레이션 해야한다.
즉 …0003, 0004이렇게 필요한 것들이 모두 마이그레이션이 되고 0005번이 마이그레이션 된다.
반대로 0005번을 취소하려면 0005번에 디펜던시가 있는 …0007, 0006번들을 먼저 취소하고 마지막에 0005번이 취소된다.
주의사항
취소
마이그레이션을 통해 테이블을 삭제하고 나면 데이터는 삭제되고 복구할 수 없다.
0005에 있던 필드를 삭제하고 0006 마이그레이션 한 후에 다시 0005로 돌아가면 컬럼은 다시 생기지만 데이터는 비어있게 된다.
테이블에 컬럼 추가
age = models.IntegerField()이렇게
모델에 필드를 새로 추가하고 마이그레이션을 하면 에러가난다.
이미 테이블에 값들이 저장되어 있기 때문에 age컬럼을 새로만들면 기존의 값들에 age컬럼이 빈 상태로 들어가는데 null=True옵션을 주지 않으면 null값이 들어갈 수 없기 때문이다.
이때 장고에서 2가지 옵션이 있는데 1번은 디폴트 값을 수동으로 입력하고
2번은 모델 필드에서 디폴트 값을 정의한다.
2번을 선택하면 필드에서 default옵션을 주면 된다.
default=30을 하면 기본값으로 모두 30이 저장된다.
만약 unique=True옵션을 주고 default를 주면 중복에러가 나게된다.
unique를 True로 하려면 default대신 null=True옵션을 줘서 일단 빈 값을 허용하고 쉘이나 어드민 페이지에서 값을 넣어주면 된다.
데이터 마이그레이션
마이그레이션은 데이터도 다룰 수 있다.
테이블 구조에 맞게 데이터를 옮겨줘야 할 때 사용한다.
새로운 필드를 만들고 값을 채워넣으려면
모델에 새로운 필드를 추가하고 마이그레이션을 만든다.
그리고 비어있는 마이그레이션 파일을 만들고 직접 작성한다.
python manage.py makemigrations –empty coplate –name “populate_email_domain”
empty옵션을 사용해 빈 마이그레이션 파일을 생성한다.
def save_email_domain(apps, schema_editor):
User = apps.get_model('coplate', 'User')
for user in User.objects.all():
user.email_domain = user.email.split('@')[1]
user.save()
class Migration(migrations.Migration):
dependencies = [
('coplate', '0006_user_email_domain'),
]
operations = [
migrations.RunPython(save_email_domain, migrations.RunPython.noop),
]
이런식으로 작성한다.
그리고 마이그레이션을 적용하면 작동된다.
마이그레이션이 적용될 때 함수를 실행시키려면 migrations.RunPython()을 사용한다.
마이그레이션이 취소될 때는 아무것도 할 필요가 없다.
어차피 컬럼이 삭제되기 때문인데 이 때 아무것도 안 한다는 것을 알리려면 migrations.RunPython.noop를 사용하면 된다.
Leave a comment