마이그레이션 파일을 만들 때 가끔 RunPython을 돌리는 경우가 있습니다. 예를 들자면, 빈 게시물의 경우 '-'을 남긴다던지 하는 식입니다. 이 때, django의 models.py에 있는 메타 정보와 마이그레이션 당시 메타 정보가 일치하지 않아서 migration이 되지 않는 문제가 발생할 수 있습니다. 이에 대해 간단하게 알아보겠습니다.

 


 먼저, app의 showmigrations를 봅시다. 보면 0003까지는 잘 적용되었는데, 0004가 적용되지 않았음을 알 수 있습니다.

 

 

 app의 0004번 migration 파일은 위와 같습니다. 먼저, gen_random_str은 랜덤한 문자를 생성합니다.

 

 

 다음에, reply의 content가 비어 있는 경우, 15자의 랜덤한 문자열을 생성해서 댓글에 저장합니다.

 

 

 이 마이그레이션 파일은 0003이 실행되고 난 후에 실행됩니다. 해당 마이그레이션을 적용해 보겠습니다.

 

 no such column: app_reply.created가 떨어졌습니다. 필드가 없다고 합니다. models.py에 들어가 봅시다.

 

 

 Reply 모델을 보면 created가 있습니다.

 

 

 그런데, 0003 마이그레이션 파일에서는 Reply model을 생성하는데요. id, content, user로 이루어진 테이블을 생성합니다. 필드 created가 없음을 알 수 있는데요. 이를 보았을 때, models.py에 있는 메타와 0004를 적용하기 직전 reply의 메타가 일치하지 않아서 발생함을 알 수 있습니다.

 

 더 정확한 원인은, Reply.objects.all()로 model을 직접 import 했기 때문입니다. 문서의 warning에도 언급되는 부분입니다. 읽다 보면, historical models 라는 용어가 나옵니다.

 

 


 이게 무엇인지 문서를 보고 이해한 내용을 바탕으로 써 보도록 하겠습니다. 먼저, migration 파일이 요래 쌓인다고 해 보겠습니다.

 

 

 0001에 id와 content 필드가 있는 Reply 모델이 생성되었고, 0003에 created가 추가되었다고 해 보겠습니다.

 

 그러면, 시점 0001과 0002에서는 historical Reply model은 id와 content가 있는 것입니다. 0003은 여기에 created가 추가되는 것입니다. 결국 문서에서 말하는 historical model이란, 마이그레이션이 됨에 따라 모델에 필드가 추가되거나 삭제가 될 텐데, 그러한 상태를 저장하는 것이라고 생각하면 됩니다.

 

 

 이제 문제 상황을 다시 정리해 봅시다. app의 0004를 실행하기 직전에, 실제 데이터 베이스의 Reply 테이블에는 id와 content 컬럼만 받게끔 되어 있어요. 그런데, Reply.objects.all()을 했습니다. models.py에는 created라는 필드가 있었기 때문에, created가 없다고 에러가 떴었습니다.

 

 어떻게 하면 될까요? historical model을 get_model 메서드를 사용해서 불러오면 됩니다.

 

 

 이 역할을 get_model 함수가 합니다. 이 경우 0004를 적용하기 직전의 "id", "content", "user"만 있는 Reply 모델을 불러옵니다.

 

 그러면 설령 models.py에 "created"라는 것이 있어도, migration이 돌 겁니다. 왜냐하면 models.py에 있는 메타를 불러오지 않았기 때문입니다.

 

 

 마이그레이션이 적용되었다면, 기존에 빈 reply의 경우 랜덤하게 생성한 길이 15자의 문자열이 들어갔음을 확인할 수 있습니다.