TIL | Django - Actor & Movie


📑ERP型式



📔Models.pyの作成

from django.db import models

#배우 테이블 작성(이름, 성, 생일, 출연한 영화(M2M))
class Actor(models.Model): 
    first_name = models.CharField(max_length = 20)
    last_name = models.CharField(max_length = 10)
    date_of_birth = models.DateField(auto_now = False, auto_now_add = False) #안에 파라미터는 안적어도 상관 없음
    movie = models.ManyToManyField('Movie') #Movie 테이블과 Many To Many 관계, 파라미터로 relative_name 넣어주면 역참조할 때 편함 :)
    class Meta:
        db_table = 'actors'
        
class Movie(models.Model):
    title = models.CharField(max_length = 80)
    release_date = models.DateField()
    running_time = IntegerField()
    class Meta:
        db_table = 'movies'
ActorクラスではManyToManyFieldと宣言され、MovieテーブルとM 2 M関係を形成する.
Djangoでは、ManyToManyFieldを宣言すると、自動的に中間テーブル(または中継テーブル)が生成されます.したがって、classを別途作成する必要はありません.

でも!


後で中間テーブルにフィールドを追加する必要がある場合は、変更は困難です.djangoが自動的に作成した中継テーブルは、接続された2つのテーブルの各idのみを参照するためです.
このように...

モデル定義が完了したら移行します.
python manage.py makemigration
python manage.py migrate

🔗views.pyの作成

import json
from django.http import JsonResponse
from django.views import View

class ActorView(View):
    def get(self, request):
        res = []
        actors = Actor.objects.all()
        for actor in actors:
            movie = list(actor.movie.values('title')
            res.append(
                {
                    "last_name" : actor.last_name
                    "first_name" : actor.first_name
                    "movies" : movie
            	}
            )
        return JsonResponse({'results' : res}, status = 200)
        
class MovieView(View):
    def get(self, request):
        res = []
        movies = Movie.objects.all()
        for movie in movies:
            actor_res = []
            actors = movie.actor_set.all()
            for actor in actors:
                actor_res.append(
                    {
                        "name" : actor.name
                    }
                )
            res.append(
                {
                    "movie name" : movie.title
                    "running time" : movie.running_time
                    "appearance" : actor_res
                }
            )
        return JsonResponce({'results' : res}, status = 200)
ビューで論理が実装されている場合は、各エンドポイントが登録されます.

✉️urls.pyの作成


mainのURL。py

# main(manage.py가 있는 디렉토리)에서의 urls.py
from django.urls import path, include

urlpatterns = [
    path('movies/', include('movies.url')),
]

appのurls。py

# app(movies 디렉토리)에서의 urls.py
from django.urls import path
from movies.views import *

urlpatterns = [
    path('actor', ActorView.as_view()),
    path('movie', MovieView.as_view())
]
最初にmainのurls.pyを介してurlに'movies/'を追加します.その後、includeのファイルにpathを追加します.仮想クライアント(httpieユーティリティ)をインストールしてリクエストを送信します.
brew install httpie
インストールが完了したら、リクエストを送信します.
http -v GET 127.0.0.1:8000/movies/actor
まずmainによって定義されたpath moviesによってmovies.urlが呼び出され、appによって定義されたpath actorによってActorViewクラスの論理が実行される.GET方式でリクエストが発行されるようになったのでgetメソッドを実行する.

🧧ManyToManyFieldの使用と中継テーブルの作成の違い

ManyToManyFieldを使用して自動的に中継テーブルを生成します.ManyToManyFieldを使用せずに中継テーブルを個別に作成し、ForeignKeyを使用して2つのテーブルを接続すると、不便が増加します.
例えば、俳優情報を含む表と映画情報を含む表がある場合、1人の俳優が複数の映画に現れる可能性がある.したがって、2つのテーブルはManyToMany関係です.
俳優が登場する映画のカタログを確認するには、中継表を通じて俳優のidとマッピングされた映画のidを見つけ、映画のidのタイトルを見つける必要がある.
しかし、ManyToManyFieldを発表すれば、俳優が出演する映画のタイトルを調べるために、このように簡単に近づくことができる.
しかし、これは必ずしもactor.movie.titleを必要とするわけではありません.今後、ある俳優が出演する映画の監督フィールドを増やしたいなら、ManyToManyFieldと発表すれば、希望するフィールドを追加するのは難しい.したがって、テーブルを個別に定義するのも良い方法です.