TIL no.32 Django through, related_name 속성

백선호·2021년 7월 21일
0

TIL

목록 보기
29/39
post-thumbnail

모델을 작성할 때 M2M 관계에서 ManyToManyField 사용하면 중간 테이블을 생성하지 않아도 django에서 자동으로 생성해 준다. 그때 테이블 간의 속성값이 존재하는데 그중 두 개 through, relate_name 속성을 설명하겠다.

Through 속성

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을 설정해야 한다.

profile
baik9261@gmail.com

0개의 댓글