모델을 작성할 때 M2M 관계에서 ManyToManyField 사용하면 중간 테이블을 생성하지 않아도 django에서 자동으로 생성해 준다. 그때 테이블 간의 속성값이 존재하는데 그중 두 개 through, relate_name 속성을 설명하겠다.
class Actor(models.Model):
first_name = models.CharField(max_length=45)
last_name = models.CharField(max_length=45)
date_of_birth = models.DateField()
class Meta:
db_table = 'actors'
class Movie(models.Model):
title = models.CharField(max_length=45)
release_date = models.DateField()
running_time = models.IntegerField()
actors = models.ManyToManyField(Actor, through='ActorMovie')
class Meta:
db_table = 'movies'
class ActorMovie(models.Model):
actor = models.ForeignKey('Actor', on_delete=models.CASCADE)
movie = models.ForeignKey('Movie', on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = 'actormovie'
상위 코드를 기반으로 설명을 하자면 M2M 관계에서 through 속성은 actormovie은 actor와 movie 관계의 중개 모델 역할은 한다. 즉 커스텀 한 중개 모델을 지정해서 사용하는 방법이다. 따라서 중간 테이블에서 바로 상대 테이블의 참조가 가능하다. 만약 through 옵션을 사용하지 않을 경우 중간 테이블에 직접 접근하여 객체로 사용하는 것이 불가능하다.
related_name이 사용될 때는 1:N의 관계에서 1이 N을 역참조할 때 사용된다.
즉 어떤 column을 기준으로 역참조를 해하는지 알 수가 없다. 상위 사진대로 예를 들어보면 airpotr 테이블이 path 테이블을 역 참조한다고 가정했을 때 destination 인지 departure 인지 알 수가 없다. 따라서 related_name을 찾아서 지정해 줘야 한다.
from django.db import models
class Airport(models.Model):
name = models.CharField(max_length=45)
class Meta:
db_table = 'airports'
class Path(models.Model):
airline = models.CharField(max_length=45)
departure = models.ForeignKey('Airport', on_delete=models.CASCADE, related_name="path_departure")
destination = models.ForeignKey('Airport', on_delete=models.CASCADE, related_name="path_destination")
class Meta:
db_table = 'paths'
역참조를 할 경우 보통 _set을 사용하지만, related_name을 지정한다면, _set을 사용하지 않아되 된다. 상위 코드와 달리 related_name을 설정하지 않는다면 migration이 되지 않고 오류가 발생한다. 따라서 related_name을 설정해야 한다.