0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Django】映画の詳細を見たい!キャストの詳細を見たい!

Last updated at Posted at 2023-03-02

PF開発進んでいます。
記事書くペースが遅いので、もうかなり進んでいるのですが、自分の復習も兼ねて情報発信していきます。

前回のフローチャート図より引用してきました。
本日は黄色で囲った所をやっていきます。

Inkedスクリーンショット 2023-03-01 161759.jpg

ちなみに前回までの実装は↓です

映画の詳細を見たい!キャストの詳細を見たい!

本日は映画ポスターをクリックすると
・映画の詳細
・キャストの詳細
・クルー
が見れるようにします。

これが映画の詳細です。
この映画おすすめです。何回見ても泣いちゃいます。
スクリーンショット 2023-03-01 162649.png

そしてキャストの詳細。
マ・ドンソク兄貴、昨日誕生日だったんですね。おめでとうございました。
スクリーンショット 2023-03-01 163042.png

映画の詳細の概要は日本語対応しているんですが、キャストのプロフィールは日本語対応していないんですよ。
自動で翻訳して出せないかなって思ったんですが、そういった機能はできなさそう...(あったら教えてください。。)

今回書いていくコード

・urls.py(お馴染み)
・views.py(お馴染み)
・detail.html(映画詳細のHTML)
・cast-detail.html(キャスト詳細のHTML)

urls.py

urls.pyはこんな感じ
  

urlpatterns = [  
    path('detail/<int:id>', views.DetailCinemaView.as_view(),name='detail'),
    #映画詳細表示
    path('detailcast/<int:id>', views.DetailCastView.as_view(),name='cast'),
    #キャスト詳細表示
]

views.py

長いので分けて書きます。 

 

  
SEARCH_URL2 = 'https://api.themoviedb.org/3/movie/{movie_id}?api_key={my_api_key}&language=ja-JP&format=json'

SEARCH_URL3 = 'https://api.themoviedb.org/3/movie/{movie_id}/credits?api_key={my_api_key}&language=ja-JP'



def get_api_data2(movie_id):
    url = SEARCH_URL2.format(movie_id=movie_id)
    api = requests.get(url).text
    result = json.loads(api)
    return result


def get_api_data3(movie_id):
    url = SEARCH_URL3.format(movie_id=movie_id)
    api = requests.get(url).text
    result = json.loads(api)
    cast_i = result["cast"]
    return cast_i

def get_api_data4(movie_id):
    url = SEARCH_URL3.format(movie_id=movie_id)
    api = requests.get(url).text
    result = json.loads(api)
    crew_i = result["crew"]
    return crew_i

TMDbのAPIを取得します。
詳細とキャスト、クルーのAPIをとってきますので
前回とは違うURLから取得してきます。
TMDbより使いたいAPIを探してきます。

スクリーンショット 2023-03-01 174940.png

映画詳細は↑

スクリーンショット 2023-03-02 092143.png

キャスト詳細は↑

それぞれ載っていますので、それをコピーしてきてください。

ちなみにPOSTMANでURLを送信すると

スクリーンショット 2023-03-01 174815.png

このようになります。前回は['result']で区切られていましたが、今回はそのようなデータになっていないためコードが少し異なります。
キャストは前回と同じ形で、castのデータとcrewのデータを[]でとってきます↓

cast_i = result["cast"]


crew_i = result["crew"]

  


class DetailCinemaView(DetailView):
#映画の詳細を呼び出すview(cinema,cast,crewそれぞれをとってくる)
    def get(self, request, *args, **kwargs):
        movie_id = self.kwargs["id"]
        items = get_api_data2(movie_id)
        cast = get_api_data3(movie_id)
        crew = get_api_data4(movie_id)

        cinema_data = {
            'title': items['title'],
            'overview': items['overview'],
            'image': items['poster_path'],
            'release_date': items['release_date'],
            'id': items['id']
        }

        cast_datalist = []
        for i , item in enumerate(cast):
            if i == 8:  #8回繰り返します
                break
            cast_name = item['name']
            cast_image = item['profile_path']
            cast_character = item['character']
            cast_id = item['id']

            cast_data = {
                'cast_name': cast_name,
                'cast_image': cast_image,
                'cast_character': cast_character,
                'cast_id': cast_id,
            }
            cast_datalist.append(cast_data)

        crew_datalist = []


        for i , item in enumerate(crew):
            if i == 8:
                break

            crew_name = item['name']
            crew_image = item['profile_path']
            crew_job = item['job']
            crew_id = item['id']

            crew_data = {
                'crew_name': crew_name,
                'crew_image': crew_image,
                'crew_job': crew_job,
                'crew_id': crew_id,
            }
            crew_datalist.append(crew_data)            

        return render(request, 'app/detail.html', {
            'cinema_data': cinema_data,
            'cast_datalist': cast_datalist,
            'crew_datalist': crew_datalist
        })

pythonの範囲ですが、enumerate関数はカウントアップです。
それぞれとってきた順番に番号をつけ、その順番が8になるまで繰り返し、8になったら終了させるようにしています。
キャストの顔写真は横スクロールも検討していますが、今回は取り急ぎの機能実装を心掛けてますので、このようにしております。


SEARCH_URL4 = 'https://api.themoviedb.org/3/person/{person_id}?api_key={my_api_key}&language=en-US'
#言語設定をja-JPにすると対応する言語がないので、空欄になってしまうため、en-USにしてあります。


SEARCH_URL5 = 'https://api.themoviedb.org/3/person/{person_id}/movie_credits?api_key={my_api_key}&language=ja-JP'



def get_api_data5(person_id):
    url = SEARCH_URL4.format(person_id=person_id)
    api = requests.get(url).text
    result = json.loads(api)
    return result
#キャスト詳細をとってきます。
def get_api_data6(person_id):
    url = SEARCH_URL5.format(person_id=person_id)
    api = requests.get(url).text
    result = json.loads(api)
    cast_film = result["cast"]
    return cast_film
#出演している映画のデータをとってきます。

  

class DetailCastView(DetailView):
#キャスト詳細を呼び出すview
    def get(self, request, *args, **kwargs):
        person_id = self.kwargs["id"]
        cast_detail = get_api_data5(person_id)
        cast_detail_film = get_api_data6(person_id)

        cast_detail_list ={
            'name': cast_detail['name'],
            'birthday': cast_detail['birthday'],
            'image': cast_detail['profile_path'],
            'biography':cast_detail['biography'],

        }



        cast_film_list = []
        for i , item in enumerate(cast_detail_film):
            if i == 8:
                break
            film_title = item['title']
            relesedate = item['release_date']
            image = item['poster_path']
            cinema_id = item['id']

            cast_detail_film_data ={
                'film_title': film_title,
                'releasedate': relesedate,
                'image': image,
                'cinema_id': cinema_id,
            }
            cast_film_list.append(cast_detail_film_data)

        return render(request, 'app/cast-detail.html',{
            'cast_detail_list': cast_detail_list,
            'cast_film_list': cast_film_list
        })

detail.html

  

{% extends 'app/base.html' %}

{% block content %}

<div class="my-5">
    <div class="row">
        <div class="col-md-6 text-center">
            <img src="http://image.tmdb.org/t/p/w154{{ cinema_data.image }}" alt="画像です" class="img-fluid">
        </div>
        <div class="col-md-6">
            <div class="card">
                <div class="card-body px-2 py-1">
                    <div class="p-4">
                        <h3>{{ cinema_data.title }}</h3>
                        <form method="POST" action="{% url 'create' %}">
                            {% csrf_token %}
                            <input type="hidden" name="title" value="{{ cinema_data.title }}">    
                            <input type="hidden" name="number" value="{{ cinema_data.id }}">
                            <input type="hidden" name="image" value="{{ cinema_data.image }}">
                            <button type="submit" class="btn btn-primary">登録する</button>
                            <button type="submit" class="btn btn-primary">レビューを見る</button>
                        </form>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>


<div class="mb-5">
    <h5>概要</h5>
    <hr>
    <p>{{ cinema_data.overview }}</p>
    <p>公開日:{{ cinema_data.release_date }}</p>
</div>

<div class="cast-container">
  {% for cast in cast_datalist %}
  <div class="card" style="width: 8rem;">
        <img class="card-img-top" src="https://image.tmdb.org/t/p/w154/{{ cast.cast_image }}" alt="card image cap">
        <div class="card-body">
            <h5 class="card-title">{{ cast.cast_character }}/{{ cast.cast_name }}</h5>
        </div>
        <a href="{% url 'cast' cast.cast_id  %}" class="stretched-link"></a>
  </div>
  {% endfor %}
    {% for crew in crew_datalist %}
    <div class="card" style="width: 8rem;">
          <img class="card-img-top" src="https://image.tmdb.org/t/p/w154/{{ crew.crew_image }}" alt="card image cap">
          <div class="card-body">
              <h5 class="card-title">{{ crew.crew_job }}/{{ crew.crew_name }}</h5>
          </div>
          

    </div>
    {% endfor %}
</div>

{% endblock %}

途中、「登録する」と「レビューを見る」のフォームを作っていますが、今回は説明しません。
DetailCinemaView(DetailView)でとってきたデータを

        return render(request, 'app/detail.html', {
            'cinema_data': cinema_data,
            'cast_datalist': cast_datalist,
            'crew_datalist': crew_datalist
        })

のように返しておりますので、それぞれこのデータを{{}}と{% %}で使い表示させるようにします。

cast-detail.html

  

{% extends 'app/base.html' %}

{% block content %}


<div class="my-5">
    <div class="row">
        <div class="col-md-6 text-center">
            <img src="http://image.tmdb.org/t/p/w154{{ cast_detail_list.image }}" alt="画像です" class="img-fluid">
        </div>
        <div class="col-md-6">
            <div class="card">
                <div class="card-body px-2 py-1">
                    <div class="p-4">
                        <h3>{{ cast_detail_list.name }}</h3>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>


<div class="mb-5">
    <h5>プロフィール</h5>
    <hr>
    <p>プロフィール:{{ cast_detail_list.biography }}</p>
    <p>誕生日:{{ cast_detail_list.birthday }}</p>
</div>

<div class="cast-container">
  {% for cast in cast_film_list %}
  <div class="card" style="width: 8rem;">
        <img class="card-img-top" src="https://image.tmdb.org/t/p/w154/{{ cast.image }}" alt="card image cap">
        <div class="card-body">
            <h5 class="card-title">{{ cast.film_title }}</h5>
            <h5 class="card-title">{{ cast.releasedate }}</h5>
        </div>
        <a href="{% url 'detail' cast.cinema_id  %}" class="stretched-link"></a>
  </div>
  {% endfor %}
</div>
{% endblock %}

キャストの方もほぼ同じです。

終わりに

上記コードを書けば、検索した映画の詳細、また出ているキャスト・クルーも見れて、尚且つキャストをクリックしたら、キャストの詳細も見れちゃうシステムです。
ここは正直必要ない機能かもしれませんが、データの扱い方を学ぶということで非常に勉強になりました。

POSTMANでデータを見るというもの大事ですし、書かれている内容を把握しJSON形式の文字列からjson.loads(api)で辞書型に直すということも学べました。

次はマイリストに登録するという機能をやっていこうと思います。

最後まで読んでいただきありがとうございました!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?