ManytoMany Table로 구성된 배우정보와 영화정보를 이용해 GET 메소드를 구현해보자.
다대다 관계인 배우 테이블과 영화 테이블을 만들고 영화 테이블에
ManyToManyField
를 지정해주었다. 또한, 중간 테이블도 따로 만들어서through
로 연결했다.
# movies.models.py
from django.db import models
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()
actor = models.ManyToManyField(Actor, through='ActorMovie')
class Meta:
db_table = 'movies'
-> 영화 테이블 작성
ManyToManyField
를 영화 테이블에 넣어주었다.ManytoManyField
는 중간 테이블을 자동으로 생성해준다.through
값에 추가하면 중간 테이블에서 또다른 필드를 만드는 등 커스터마이징 가능하다. -> 확장성이 좋아진다.class ActorMovie(models.Model):
actor = models.ForeignKey(Actor, on_delete=models.CASCADE)
movie = models.ForeignKey(Movie, on_delete=models.CASCADE)
class Meta:
db_table = "actors_movies"
-> 중간 테이블 작성
두 개의 FK로 연결하면 영화 테이블에 ManytoManyField
가 없어도 문제없다.
하지만 ManytoManyField
의 through
로 지정해주지 않으면 다른 테이블로 접근할때 매번 중간 테이블을 거쳐야한다. -> 아주 비효율적이며 번거롭다.
related_name
옵션은 무엇이고 언제쓸까?ManyToManyField 뿐만 아니라 ForeignKey 필드에도 사용할 수 있는 옵션이다.
참조 관계의 테이블에서 손쉽게 역참조/정참조를 할 수 있게 해 준다.
옵션 값으로는 상대 테이블에서 해당 테이블을 참조할 때 쓰는 이름을 값으로 주면 된다.
-> 위에서 related_name="actors"
로 하면 배우 테이블에서 actors라는 이름으로 출연 영화 정보를 가져올 수 있다.
이 옵션은 M:N관계에서 사용하기보단 셀프 참조를 하는 테이블에 유용하게 쓰인다.(self 참조 시에는 related_name이 필수다)
- 등록된 배우 목록을 가져올 수 있는 GET 메소드 구현하기.
-> 이름, 출연 영화 제목
import json
from django.http import JsonResponse
from django.views import View
from movies.models import Actor, Movie
class ActorView(View):
def get(self, request):
actor_list = []
actors = Actor.objects.all()
for actor in actors:
movie_list = []
movies = actor.movie_set.all() # 역참조
for movie in movies:
movie_list.append(movie.title)
actor_info = {
"name" : actor.last_name + actor.first_name,
"movie_list" : movie_list
}
actor_list.append(actor_info)
return JsonResponse({'result':actor_list}, status=200)
모든 배우 정보를 순회하며 출연 영화 정보를 반환한다.
배우 테이블에서 영화 정보로 접근하기 위해 역참조를 한다. (actor.movie_set
)
배열에 담아 리턴한다.
- 등록된 영화 목록을 가져올 수 있는 GET 메소드 구현하기.
-> 제목, 상영시간, 출연 배우 이름
class MovieView(View):
def get(self, request):
movie_list = []
movies = Movie.objects.all()
for movie in movies:
actor_list = [{
'name': actor.last_name + actor.first_name}
for actor in movie.actor.all()]
movie_list.append(
{
"title" : movie.title,
"running_time" : movie.running_time,
"actor_list" : actor_list
}
)
return JsonResponse({'result':movie_list}, status=200)
배우 정보와 비슷한 로직이지만 파이썬의 List Comprehension을 이용했다.
특정 영화에 출연한 배우 정보를 순회하며 이름을 배열에 담는다.
영화 테이블에서 배우 정보로 접근하는 것은 정참조이다.
from django.urls import path
from movies.views import ActorView, MovieView
urlpatterns = [
path('/actor', ActorView.as_view()),
path('/movie', MovieView.as_view()),
]
작성한 두개의 view에 대해 urls.py를 작성해준다.
프로젝트 폴더의 urls.py에는 include()
함수와 함께 movies 앱의 경로를 지정해준다.
추후 POST 메소드도 구현해보자.