📝 지난 Database 포스팅에서 언급하였듯, Many to Many(N:N) 관계는 두 테이블을 연결하고 관계를 나타내는 중간 테이블이 필요하다. django에서도 model 구현시 중간테이블을 생성해야 하는데 직접 중간테이블을 생성하는 방법과 ManytoManyField를 사용하는 방법이 있다.
#직접 중간테이블을 생성한 model
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(default=0)
class Meta:
db_table = 'movies'
class Actor_movie(models.Model):
actor = models.ForeignKey('Actor', on_delete = models.CASCADE)
movie = models.ForeignKey('movie', on_delete = models.CASCADE)
class Meta:
db_table = 'actors_movies'
👉 Foreign key를 사용하여 직접 중간테이블(Actor_movie)을 직접 생성한 model이다.
👉 actors_movies 테이블에 직접 데이터를 삽입하여 연결해 주어야 한다.
👉 데이터 접근시 중간테이블을 역참조하고 연결테이블을 통해서 값을 가져와야하는 불편함이 있다.
#manytomanyfield를 사용한 model
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(default=0)
actor = models.ManyToManyField(Actor, related_name='movies')
class Meta:
db_table = 'movies'
👉 ManyToManyField
를 사용하여 Many to Many 모델을 구현한 models.py의 코드이다.
👉 relate_name
을 사용하면 역참조시 사용되는 _set
은 사용하지 않아도 된다.
👉 through 옵션을 사용한 중간테이블 컨트롤이 가능하다.
👉 자동 생성된 중간테이블에 데이터 삽입은 아래와 같이 add()
를 통해 가능하다.
# $ python manage.py shell
>>> a1 = Actor.objects.get(id=1)
>>> m2 = Movie.objects.get(id=1)
>>> m1.actor.add(a1)
>>> a2 = Actor.objects.get(id=2)
>>> m2 = Movie.objects.get(id=2)
>>> m2.actor.add(a2)
✅ 끝으로 ManyToManyField 사용의 장점을 정리해보면,
1) 중간테이블을 따로 생성하지 않아도, Django에서 자동으로 만들어준다는 편리함이 있다.
2) Views.py에서 클래스형 뷰 구현시 중간테이블을 거치지 않아도 되므로 코드가 짧아지고 직관적이며, 가독성이 좋아진다.
3) Query method를 사용하여 비교적 CRUD가 간편하다.