[Django] C.R.U.D -2 (2)

김가람휘·2022년 2월 15일
2

Django

목록 보기
8/13

배우와 영화

# 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 사용하는 이유

  • 중간 테이블을 거치지 않고, 언제든지 데이터를 쉽게 추가하고 가져올 수 있다.
  • 유지보수가 편리하다.
  • MTM필드를 사용하면 자동으로 Class_Class 형태로 Database에 table을 생성해준다.
  • MTM필드는 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)

0개의 댓글