[Django] C.R.U.D -2 (2)
俳優と映画
# movies.models.py
from django.db import models
class Actor(models.Model):
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=20)
date_of_birth = models.DateField()
# though를 지정해주지 않으면 다른 테이블로 접근할 때 매번 중간 테이블을 거쳐야한다.
# actor -> movie 정참조, movie -> actor 역참조
movies = models.ManyToManyField("Movie", through="Actor_Movie", related_name="actors")
# related_name을 지정해주면 역참조할 때 사용할 수 있다.
class Meta:
db_table = 'actors'
# MTM를 사용하면 자동으로 Class_Class형태로 DB에 중간table이 생성된다.
# 사용자가 직접 중간테이블을 만들고 through값에 추가하면 중간테이블에서 필드를 추가하는 커스터마이징 가능하다. -> 확장성 ↑
# 두 개의 FK로 연결하면 MTM필드가 없어도 오류는 없으나 다른 테이블로 접근할때마다 매번 중간테이블을 거쳐야한다. -> 비효율적
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'
class Movie(models.Model):
title = models.CharField(max_length=20)
release_date = models.DateField()
running_time = models.IntegerField()
class Meta:
db_table = 'movies'
# main/urls.py
from django.urls import path, include
urlpatterns = [
path('', include('movies.urls'))
]
# movies/urls.py
from django.urls import path
from movies.views import ActorsView, MoviesView
urlpatterns = [
path('actors', ActorsView.as_view()),
path('movies', MoviesView.as_view())
]
# movies/views.py
from django.http import JsonResponse
from django.views import View
from movies.models import Actor, Movie
class ActorsView(View):
def get(self, request):
actors = Actor.objects.all() # actor테이블의 모든 레코드를 querySet으로 가져온다.
results = [] # 배우의 이름과 성, 출연한 영화 제목 목록을 출력할 리스트
for actor in actors: # actor테이블의 모든 레코드를 돈다.
movie_lists = [] # movie를 담을 리스트 생성
movies = actor.movies.all() # MTM관계 지정을 했으므로 중간 테이블없이 movies 값을 가져올 수 있다.
for movie in movies: # movie테이블의 모든 레코드를 돈다.
# 각 actor에 맞는 movie리스트를 추가한다.
movie_lists.append({
"title" : movie.title # 영화 제목을 가져온다.
})
results.append({ # 배우의 이름, 영화 목록을 추가한다.
"first_name" : actor.first_name,
"last_name" : actor.last_name,
"movie" : movie_lists
})
return JsonResponse({'resutls':results}, status=200)
class MoviesView(View):
def get(self, request):
movies = Movie.objects.all()
results = []
for movie in movies:
actor_lists = [] # actor를 담을 리스트 생성
# movies안의 각각의 movie에 맞는 actors객체를 전부 가져온다.
# MTM을 사용하지 않는다면 중간테이블에서 값을 가져와야한다.
actors = movie.actors.all()
# movie에서 actor 참조는 역참조이다. actor_set
# related_name에 actors를 대입해주었기에 사용가능하다.
for actor in actors:
# actor테이블의 모든 레코드를 돈다.
# 각 movie에 맞는 actor리스트를 추가한다.
actor_lists.append({
"name" : actor.first_name
})
results.append( # 영화의 제목, 러닝타임, 배우 목록을 추가한다.
{
"title" : movie.title,
"running_time" : movie.running_time,
"actor" : actor_lists
}
)
return JsonResponse({'resutls':results}, status=200)
http -v GET 127.0.0.1:8080/movies
http -v GET 127.0.0.1:8080/actors
なぜManyToManyFieldを使うのですか?
related_name+s
です.ex) movie_set (x) -> movies
(修正)俳優と映画のPOSTを実現!
# movies/urls.py
from django.urls import path
from movies.views import ActorsView, MoviesView, Actors_MoviesView
urlpatterns = [
path('actors', ActorsView.as_view()),
path('movies', MoviesView.as_view()),
path('actors_movies', Actors_MoviesView.as_view())
]
# movies/views.py
import json
from django.http import JsonResponse
from django.views import View
from movies.models import Actor, Actor_Movie, Movie
class ActorsView(View):
def get(self, request):
actors = Actor.objects.all()
results = []
for actor in actors:
movie_lists = []
movies = actor.movies.all()
for movie in movies:
movie_lists.append({
"title" : movie.title
})
results.append({
"first_name" : actor.first_name,
"last_name" : actor.last_name,
"movie" : movie_lists
})
return JsonResponse({'resutls':results}, status=200)
def post(self, request):
try:
data = json.loads(request.body)
Actor.objects.create(
first_name = data['first_name'],
last_name = data['last_name'],
date_of_birth = data['date_of_birth']
)
return JsonResponse({'messasge':'created'}, status=201)
except KeyError:
return JsonResponse({'message' : 'KEY_ERROR'},status=400)
class MoviesView(View):
def get(self, request):
movies = Movie.objects.all()
results = []
for movie in movies:
actor_lists = []
actors = movie.actors.all()
for actor in actors:
actor_lists.append({
"name" : actor.first_name
})
results.append(
{
"title" : movie.title,
"running_time" : movie.running_time,
"actor" : actor_lists
}
)
return JsonResponse({'resutls':results}, status=200)
def post(self, request):
try:
data = json.loads(request.body)
Movie.objects.create(
title = data['title'],
release_date = data['release_date'],
running_time = data['running_time']
)
return JsonResponse({'messasge':'created'}, status=201)
except KeyError:
return JsonResponse({'message' : 'KEY_ERROR'},status=400)
class Actors_MoviesView(View):
def post(self, request):
try:
data = json.loads(request.body)
Actor_Movie.objects.create(
actor_id = data['actor_id'],
movie_id = data['movie_id'],
)
return JsonResponse({'messasge':'created'}, status=201)
except KeyError:
return JsonResponse({'message' : 'KEY_ERROR'},status=400)
Reference
この問題について([Django] C.R.U.D -2 (2)), 我々は、より多くの情報をここで見つけました https://velog.io/@kimkrh/Django-C.R.U.D-2-2テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol