Django App내의 일부 테이블이 DB에 이미 존재하는 경우

2021. 6. 16. 00:10Trouble Shooting

728x90

보통 하나의 App내에 여러 테이블을 작성하면 흔히 "꼬였다." 라는 현상의 문제가 발생합니다.

Django의 migration은 강력한 기능이지만 익숙하지 않은 유저들에게는 존재 자체만으로도 스트레스를 유발하죠.

 

예를 들어 다음과 같이 News 라는 테이블이 이미 실물 데이터베이스에 존재할 경우

django.db.utils.ProgrammingError: (1050, "1050 (42S01): Table 'news' already exists", '42S01')

 

위 와 같은 오류가 발생합니다.

하지만 models.py에는 News이외 에도 명시되어 있어서 아마 이 글을 찾은 여러분들은

migrations를 초기화 해도 안돼요 ㅜㅜ 와 같은 울상을 짓고 계실겁니다.

 

 

이런 경우에는 해결방법이 3가지정도 존재합니다.

  • 이미 존재하는 'News' 테이블 제거 (사실 이건 말도 안되는...)
  • 수동으로 실물 DB에 마이그레이션파일에서 추가하는 테이블을 모두 추가... (? 개발자가 노가다를 하라니?)
  • django migration으로 인한 오류니깐 migration으로 쇼부 보기(8단계로 구성되며 생각보다 쉽습니다.)

 

 

1. Migration Cancel(마이그레이션 취소)

 

먼저 해당하는 app의 migration을 취소합니다.

python manage.py migrate --fake app zero

--fake app zero를 통해 migration을 취소합니다.

 

 

 

2. Remove Migrations File(마이그레이션 파일 제거)

해당하는 appmigrations 폴더에서 __init__.py 를 제외하고 제거합니다.

물론 Product 운영중이며, 관계(Relation)가 엮여 복잡한 테이블이 차지하고 있을 경우!

가장 최근 마이그레이션이 문제라면 해당 migration 파일만 삭제하셔야 합니다.

 

 

 

3. models.py 수정

# project/app/models.py

class News(models.Model):
    title = models.CharField(max_length=255, blank=True, null=True)
    summary = models.CharField(max_length=255, blank=True, null=True)
    write_at = models.DateTimeField(blank=True, null=True, db_column='writed_at', help_text='블리자드 표기 등록 일시')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(blank=True, null=True)

    class Meta:
        db_table = 'news'
        managed = False  # 이걸 잠깐 추가해줍니다.

already table 오류가 발생한 Model의 class Meta에 managed = False를 잠깐 추가 해주도록 합니다.

이로 인해 makemigrations로 migrations 파일 생성시 일단은 해당 테이블을 생성하지 않습니다.

 

 

4. migrations 파일 생성

python manage.py makemigrations app

해당하는 app의 migrations 파일을 생성하기위해 makemigrations <app> 을 지정하여 생성합니다.

 

 

 

5. Migrate 실행

python manage.py migrate app

1번에서 취소했던 해당 app을 지정하여 다시 migrate를 진행합니다.

Database를 확인 하면 정상적으로 Table이 생성된 걸 확인할 수 있으실겁니다.

 

 

6. models.py 복원

# project/app/models.py

class News(models.Model):
    title = models.CharField(max_length=255, blank=True, null=True)
    summary = models.CharField(max_length=255, blank=True, null=True)
    write_at = models.DateTimeField(blank=True, null=True, db_column='writed_at', help_text='블리자드 표기 등록 일시')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(blank=True, null=True)

    class Meta:
        db_table = 'news'
        #managed = False  # 제거 또는 주석 또는 True 설정

managed = False를 설정한 모델을 다시 django에서 managed(관리) 할 수 있도록 설정합니다.

 

 

 

7. migration 생성

python manage.py makemigrations app

6번의 과정으로 인해 models.py의 변경사항이 생겼으므로 4번에서 진행한 것처럼 해당 app을 대상으로

makemigrations을 진행합니다.

 

 

 

8. migrate 실행

python manage.py migrate app

다시 마지막으로 변경사항을 database에 반영 및 저장하기 위해 migrate를 실행합니다.

 

 

이제 Django에서는 더이상 error가 출력되지 않으면서, Database를 확인해보면 모두 정상적으로 생성된 것을 확인

가능합니다.

 

 

 

 

728x90