본문 바로가기

Study/BackEnd

[Django] Django model에 InheritanceManager 적용하기

데이터베이스 테이블이 많아지고 상속이 빈번해지는 등 각 테이블 간의 관계가 복잡해지면서,
상속 관계에 있는 모델들을 복잡하지 않게 관리하고자 하는 요구 사항이 생겼다.

(회사 코드를 가져올 수는 없어서 비슷한 예시로 대체한다.)

예를 들어서, 아래와 같은 관계의 모델이 있다고 해보자.

차라는 부모 클래스를 휘발유 차와 전기 차라는 자식 클래스가 상속하고 있는 형태이다.

코드로 나타내면 다음과 같이 작성될거다.

from django.db import models

class Car(models.Model):
  car_id = models.AutoField(primary_key = True)
  car_nickname = models.CharField(verbose_name = "별명")

class GasolineCar(Car):
  tank_isfull = models.Boolean(verbose_name = "주유 여부")

class ElectricCar(Car):
  is_fullCharged = models.Boolean(verbose_name = "충전 여부")

 

차라는 공통점에서 오는 공통 필드들이 있어 차라는 부모 클래스를 상속 받고,
휘발유 차인지, 전기 차인지에 따라서 정비 해야하는 부품들이 다를테니 각각 테이블이 있어야 한다.

정비한 차 목록을 모두 한 곳에서 관리해야 하기 때문에
부모 클래스인 차도 하나의 테이블로 있어야 하니 다중 클래스 상속 형태로 상속이 일어난다.



▽ 자세한 Django Model 상속에 대한 내용은 아래 포스팅 참고!! 

 

[Django] Django Model 상속 알아보기

회사에서 django를 다루면서, ORM을 공부할 일이 정말 많다. 그 중에서도 특히 model 상속과 관련된 부분을 따로 정리해보려고 한다. 1. 추상 기본 클래스 (Abstract Base Class) 추상 기본 클래스는 여러 다

it-is-my-life.tistory.com

 

만드는 것 까지는 좋은데 여기서 문제가 발생한다.

예를 들어서, car_nickname이 "suin"인 차의 부품 정비 상태를 보고 싶은 경우라고 하자

부모 테이블인 차에는 아쉽게도 해당 차가 휘발유 차인지, 전기 차인지에 해당하는 car_type을 가지고 있지 않기 때문에 나는 차의 별명을 제외하고는 어떤 정보도 갖고 있지 않다.

이런 경우에, 부모 테이블을 통해서 자식 테이블에 접근하는 것 자체가 어렵기 때문에 다른 방법이 필요하다.

이 때, 본인은 Django 외부 모듈인 Django-model-utils에 있는 InheritanceManager를 이용했다.

 

InheritanceManager란?

공식 docs에는 InheritanceManager를 다음과 같이 설명하고 있다.

It allows queries on that base model to return heterogeneous results of the actual proper subtypes, without any additional queries.

 

즉, 자식 모델에 대한 추가적인 쿼리를 사용하지 않아도 부모 모델 (base model)에 대한 쿼리만을 이용하여 다양한 결과 (heterogeneous result)를 얻을 수 있도록 하는 manager라는 말이다.

이 InheritanceManager를 이용하여 앞서 언급한 예시를 다뤄보겠다.

car_nickname이 "suin"인 차의 부품 정비 상태를 보고 싶을 때, InheritanceManager를 이용하여 다음과 같이 원하는 결과를 얻을 수 있다.

from django.db import models
from model_utils.managers import InheritanceManager

class Car(models.Model):
  car_id = models.AutoField(primary_key = True)
  car_nickname = models.CharField(verbose_name = "별명")
  objects = InheritanceManager()

class GasolineCar(Car):
  tank_isfull = models.Boolean(verbose_name = "주유 여부")

class ElectricCar(Car):
  is_fullCharged = models.Boolean(verbose_name = "충전 여부")

# car_nickname이 "suin"인 객체 생성
suin = Car.objects.select_subclasses().get(car_nickname = "suin")

 

만약 "suin"이라는 car_nickname을 가진 차가 전기 차라면 ElectricCar 객체가 생성될 것이다.

"suin" 차가 전기 차인지 휘발유 차인지를 알지 못해도 ElectricCar 객체가 생성된 것이다!!

이런 식으로 부모 클래스 만을 가지고 해당 부모 클래스를 상속받은 자식 클래스를 다룰 수 있게 된 것이다.

 

이 때, 기본 manager를 사용하고 싶다면,

from django.db import models
from model_utils.managers import InheritanceManager

class Car(models.Model):
  car_id = models.AutoField(primary_key = True)
  car_nickname = models.CharField(verbose_name = "별명")
  objects = models.Manager()
  child = InheritanceManager()

class GasolineCar(Car):
  tank_isfull = models.Boolean(verbose_name = "주유 여부")

class ElectricCar(Car):
  is_fullCharged = models.Boolean(verbose_name = "충전 여부")

# car_nickname이 "suin"인 객체 생성
suin = Car.child.select_subclasses().get(car_nickname = "suin")

# 기본 manager 이용하여 객체 생성
basic = Car.objects.all()

 

이 django manager의 경우, 커스텀해서 쓸 수도 있고 순서에 따라서 우선순위가 달라지기도 하는데 이 부분은 다음 포스팅에서 다루도록 하겠다.