Django ManyToMany

Hoontae.KIM·2021년 7월 21일
1
post-thumbnail

ManyToMany 관계 활용법

두 가지의 방법이 있다 ForeignKey를 사용하여 중간테이블을 만드는 법과 ManyToManyField를 사용하여 중간테이블을 사용하지 않고 코드를 작성할 수 있어 코드의 가독성이 좋아지는 장점이 있다.
하지만 django에서만 제공해주는 특성이기에 ManyToManyField 없이도 데이터를 가지고 올 수 있어야한다.


위 ERD 를 보고 두가지의 models.py를 작성할 수 있다.

models.py

1) ForeignKey(중간테이블)을 활용한 코드

# ForeignKey(중간테이블)을 활용한 코드
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 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=45)
    release_date = models.DateField()
    running_time = models.IntegerField()


    class Meta:
        db_table = 'movies'

2) ManyToManyField를 활용한 코드

# ManyToManyField를 활용한 코드
class Actor(models.Model):
    first_name = models.CharField(max_length=45)
    last_name = models.CharField(max_length=45)
    date_of_birth = models.DateField()
    movies = models.ManyToManyField('Movie', through=Actor_Movie)

    class Meta:
        db_table = 'actors'


class Movie(models.Model):
    title = models.CharField(max_length=45)
    release_date = models.DateField()
    running_time = models.IntegerField()


    class Meta:
        db_table = 'movies'

위 코드를 보면 2)번 코드의 경우 Actor_Movie라는 class를 따로 만들어 줄 필요없이 연결해줄 class에 ManyToManyField를 활용하여 through 속성을 주면 중간테이블을 생성해준다.

views.py

1) ForeignKey(중간테이블)을 활용한 코드

# ForeignKey(중간테이블)을 활용한 코드
class ActorsView(View):
    def get(self, request):
        actors = Actor.objects.all()
        result = []

        for actor in actors:
            movie_list = []

            for actor_movie in actor.actor_movie_set.all():
                movie_list.append({
                "title" : actor_movie.movie.title,
                "release_date" : actor_movie.movie.release_date,
                "running_time" : actor_movie.movie.running_time,
                })
            
            result.append({
                "first_name" : actor.first_name,
                "last_name" : actor.last_name,
                "date_of_birth" : actor.date_of_birth,
                "movie" : movie_list,
            })
            
        return JsonResponse({'result':result}, status=200)

class MoviesView(View):
    def get(self, request):
        movies = Movie.objects.all()
        result = []

        for movie in movies:
            actor_list = []

            for actor_movie in movie.actor_movie_set.all():
                actor_list.append({
                "first_name" : actor_movie.actor.first_name,
                "last_name" : actor_movie.actor.last_name,
                "date_of_birth" : actor_movis.actor.date_of_birth,
                })

            result.append({
                "title" : movie.title,
                "release_date" : movie.release_date,
                "running_time" : movie.running_time,
                "actor" : actor_list,
            })

        return JsonResponse({'result':result}, status=200)

2) ManyToManyField를 활용한 코드

class ActorsView(View):
    def get(self, request):
        actors = Actor.objects.all()
        result = []

        for actor in actors:
            movie_list = []

            for movie in actor.movies.all():
                movie_list.append({
                "title" : movie.title,
                "release_date" : movie.release_date,
                "running_time" : movie.running_time,
                })
            

            result.append({
                "first_name" : actor.first_name,
                "last_name" : actor.last_name,
                "date_of_birth" : actor.date_of_birth,
                "movie" : movie_list,
            })
            
        return JsonResponse({'result':result}, status=200)

class MoviesView(View):
    def get(self, request):
        movies = Movie.objects.all()
        result = []

        for movie in movies:
            actor_list = []

            for actor in movie.actors.all():
                actor_list.append({
                "first_name" : actor.first_name,
                "last_name" : actor.last_name,
                "date_of_birth" : actor.date_of_birth,
                })

            result.append({
                "title" : movie.title,
                "release_date" : movie.release_date,
                "running_time" : movie.running_time,
                "actor" : actor_list,
            })

        return JsonResponse({'result':result}, status=200)

위 코드를 자세하게 보면 기존 중간테이블을 역참조해주던 actor_movie_set을 사용하지 않고 바로 연결 할 테이블로 작성해주고 중간테이블의 actor_movie를 사용하지 않아 코드가 더욱 가독성이 높아진 걸 확인할 수 있다.
하지만 ManyToMany 테이블을 쓰던 안쓰던 결국 중간테이블을 통하여 데이터를 가져와야하는것은 같기 때문에 django 이외에 다른 프레임워크를 사용할 수 도 있기에 사용하는 것을 지양해야겠다.

profile
💻 STUDY RECORD

0개의 댓글