Django model 상속

김도연
4 min readAug 5, 2021

--

장고의 model도 파이썬의 class와 마찬가지로 서로 상속하여 사용할 수 있다. 장고 공식 문서에서 제안하는 모델 상속의 방법에는 3가지가 있다.

1. Abstract base class를 상속하기

2. 다중 테이블 상속

3. proxy model 사용하기

Abstract base class

여러 모델에서 중복으로 사용하는 필드나 공통정보가 있을 때 사용하면 좋다.
abstract base class는 데이터베이스 테이블을 생성하는데 사용되지 않고 다른 모델의 기본 클래스로만 사용된다.

from django.db import models
from django_extensions.db.models import TimeStampedModel
from safedelete import SOFT_DELETE_CASCADE
from safedelete.models import SafeDeleteModel
# 몇몇 모델에서 공유하는 필드가 있을 때
class AddressInfo(models.Model):
address = models.CharFields(max_length=100)
post_code = models.CharFiedls(max_length=5)
class Meta:
abstract = True
class User(AddressInfo):
name = models.CharFields(max_length=30)
class VipUser(AddressInfo):
...


# 각 모델에서 공통적으로 상속받는 모델이 있을 때
class DefaultModel(SafeDeleteModel, TimeStampedModel):
_safedelete_policy = SOFT_DELETE_CASCADE
class Meta:
abstract = True

class Order(DefaultModel):
pass
class Product(DefaultModel):
pass

다중 테이블 상속

일반 클래스처럼 부모 클래스를 상속받는다. 부모 모델과 자식 모델을 OnetoOneField로 두 모델을 연결한다. 테이블을 생성하지 않는 abstract base class 달리 이 경우엔 부모 클래스도 테이블을 생성한다.

다중 테이블 상속의 경우 쿼리할 때 left join이 많이 일어난다고 하는데 성능상의 이점도 분명하지 않고 암시적으로 OneToOneField로 두 모델을 연결시켜 놓기 때문에 헷갈릴 수 있다.
일반 파이썬 클래스나, abstract base class 처럼 동작하지만 부모클래스에서 실제로 테이블이 생성되는 식으로 동작하는 것이 아닐까 착각할 수 도 있다. 명시적으로 관계있는 모델끼리 엮어주는 편이 더 직관적이고 보기 편해서 유지 보수하는데 좀 더 낫지 않을까 생각한다.

class Discovery(models.Model):
engine = models.CharField(max_length=50)
payload = models.IntegerField()
class Astronaut(SpaceShip):
Time_in_space = models.IntegerField()
Launches = models.IntegerField()

Proxy model

원래 모델에 대한 프록시를 생성해서 매니저 변경이나 매소드를 추가해서 사용할 수 있다. 하나의 테이블을 여러 용도로 사용해야 할 때 쓰면 편리하다.

예를들어 주문관련 정보를 담는 Order 모델이 있고, 관리자는 정상주문과 반품/교환 주문을 따로 보고 싶다고 하자. 그럴땐 Order 모델의 프록시 모델을 생성해서 별도의 로직으로 관리할 수 있다.

class Order(models.Model):
status = models.CharField(choices=OrderType.choices)
....
class ReturnOrder(Order):
# 새로운 매니저를 사용할 수도 있다
objects = NewManger()
class Meta:
proxy = True

--

--

김도연
김도연

No responses yet