당신은 멋쟁이, 우리는 장고쟁이~

0%

Django Models 19편 - Model 상속 Multi-table inheritance 2편

Multi-table inheritance 2편


Inheritance and reverse relations


multi-table 상속은 암시적으로, OneToOneField 를 사용하여 자식 클래스와 부모 클래스를 연결해 주기 때문에, 부모 클래스에서 자식 클래스로 이동이 가능해 집니다.


하지만, 이는 ForeignKey 와 ManyToManyField 관계들을 위한 기본 related_name 값을 사용합니다.


만일 우리가, ForeignKey 나 ManyToManyField 관게들을 부모의 서브클래스에 넣어준다면, 각 필드에 related_name 속성들을 지정해 주어야 합니다.


각 필드에 이 relate_name 속성을 지정해 주지 않는다면, Django는 유효성 에러를 발생 시킬겁니다.




예시를 들면,


1
2
3
4
5
6
7
8
9
10
11
12
13
14
from django.db import models 

class Place(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=80)

class Restaurant(Place):
serves_hot_dogs = models.BooleanField(default=False)
serves_pizza = models.BooleanField(default=False)

# 새로운 서브 클래스 추가

class Supplier(Place):
customers = models.ManyToManyField(Place)

이렇게 코드를 짜면, 에러를 발생 시킵니다.


새로운 클래스를 추가하고, python manage.py makemigraitons 를 실행하면, 아래와 같은 에러가 출력 됩니다.


1
2
3
4
5
6
7
8
(django-tutorial)  dhkang  ~/django_tutorial/django_docs master python manage.py makemigrations
SystemCheckError: System check identified some issues:

ERRORS:
multitableinheritance.Supplier.customers: (fields.E305) Reverse query name
for 'Supplier.customers' clashes with reverse query name for 'Supplier.place_ptr'.
HINT: Add or change a related_name argument to the definition for
'Supplier.customers' or 'Supplier.place_ptr'.


related_name 을 아래와 같이 customers 필드에 추가를 하면, 에러가 해결됩니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from django.db import models

class Place(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=80)

class Restaurant(Place):
serves_hot_dogs = models.BooleanField(default=False)
serves_pizza = models.BooleanField(default=False)


# 새로운 서브 클래스 추가
class Supplier(Place):
customers = models.ManyToManyField(Place, related_name='provider')
# related_name='provider' 라고 지정을 해줌

related_name 을 지정해주고, python manage.py makemigrations 를 실행해주면, migrations 가 생성됩니다.


이전에도 언급되었듯이, django 는 자동적으로 OneToONeField 를 사용하여, 자식 클래스를 Abstract base 클래스가 아닌 부모 클래스 모델에 연결해 줍니다. 만약 부모와 연결되는 속성들의 이름을 제어하고 싶다면, 스스로 OneToOneField 를 생성하고, parent_link = True 로 설정하여, 당신의 필드가 부모 클래스에 뒤쪽으로 연결 된다는것을 표시할수 있습니다.