Django 공통모델 상속

HS L·2023년 6월 6일
0

내일배움캠프

목록 보기
63/73

문제

모든 모델에 공통적으로 사용하는 필드를 공통모델을 만들어 상속하여 사용하고자 했다.

class CommonModel(models.Model):
    db_status_choice = [
        (1, 'active'),
        (2, 'delete'),
    ]
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    db_status = models.PositiveIntegerField(
        choices=db_status_choice, default=1)
class EmoticonImage(CommonModel):
    emoticon = models.ForeignKey(Emoticon, on_delete=models.CASCADE, related_name='images')
    image = models.ImageField("이미지", upload_to='%Y/%m/', blank=True, default=None)

    def __str__(self):
        return f'{self.emoticon.title} - {self.image}'

위 모델을 작성한 뒤 makemigrations를 실행했을때 다음과 같은 에러가 발생했다.

$ python manage.py makemigrations
SystemCheckError: System check identified some issues:

ERRORS:
emoticons.EmoticonImage.emoticon: (models.E006) The field 'emoticon' clashes with the field 'emoticon' from model 'users.commonmodel'.

시도

에러 원인은 EmoticonImage모델의 emoticon필드가 CommonModel의 emoticon필드와 충돌한다고 한다.

- CommonModel에는 emoticon필드가 없는데 왜 에러가 나는거지...

재시작

저장이나 IDE편집기 문제인가 싶어 서버 저장 후 DB삭제, 기존 마이그레이션 정보 삭제 후 IDE편집기 재시작 후에도 동일한 에러가 발생했다.

필드명 변경

에러가 발생하는 EmoticonImage모델의 emoticon필드명을 네이밍을 변경해서 makemigrations를 진행.

→ makemigrations진행 가능

근데 왜?

이전 공통모델을 상속했을때 기억으로는 필드명관련 에러없이 동작했었다.

에러원인을 봤을때도 알 수 있듯이 CommonModel에서는 emoticon필드명이 없는 상태지만 그 부분에서 에러가 난다는 것은... 이건 뭔가가 잘못됐다....

필드명 변경 후 migration은 잘 진행이 되지만 이건 에러를 피해간 것이지 올바른 에러 해결방법이 아니라는 생각에 검색...!

Django에서 공통모델을 사용할 경우 DB에 테이블이 생성되지 않도록 Meta class를 선언해줘야 한다고 한다.
아래 해결에서 이어서 서술하겠다.


해결

공식문서에서 공통모델(추상모델)의 설명을 보면 다음과 같다.

Abstract base 클래스는 공통 정보를 다른 모델에 사용하려는 경우에 유용하다. 기본 클래스를 작성하고 메타클래스 안에 abstract=True를 넣습니다. 그러면 이 모델은 데이터베이스 테이블을 만드는 데 사용되지 않습니다. 대신 다른 모델의 기본 클래스로 사용될 때 해당 필드가 하위 클래스의 필드에 추가됩니다.

from django.db import models

class CommonInfo(models.Model):
    name = models.CharField(max_length=100)
    age = models.PositiveIntegerField()

    class Meta:
        abstract = True

class Student(CommonInfo):
    home_group = models.CharField(max_length=5)

공식문서 내용을 확인했을때 아래 코드가 빠져있음을 알 수 있다.

class Meta:
        abstract = True

설명을 보면 abstract = True가 설정되지 않으면 기본적으로 DB에 테이블을 만들게 되고 그 모델을 상속받아서 다른 모델을 만들기 때문에 필드명 충돌이 일어난 것으로 보인다.

에러가 발생한 곳에 빠진 부분을 추가해줬다.

class CommonModel(models.Model):
    db_status_choice = [
        (1, 'active'),
        (2, 'delete'),
    ]
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    db_status = models.PositiveIntegerField(
        choices=db_status_choice, default=1)

    class Meta:
        abstract = True

makemigrations 실행시 아주 잘 된다... 해결

공식문서


고찰

구현하고자하는 부분이 해당 라이브러리에서 지원하는지, 지원한다면 공식문서를 잘 읽어보고 공부하자..

profile
식이

0개의 댓글