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

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

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

![Inkedスクリーンショット 2023-03-01 161759.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2854762/65b942a9-dc31-207f-ad09-059ba4c2dc8e.jpeg)


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

https://qiita.com/ri-tama/items/aa3b4125955c7f6051fd


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


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

これが映画の詳細です。
この映画おすすめです。何回見ても泣いちゃいます。
![スクリーンショット 2023-03-01 162649.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2854762/a1d1f7cf-d663-4da3-a1fb-c0f6ebc999de.png)



そしてキャストの詳細。
マ・ドンソク兄貴、昨日誕生日だったんですね。おめでとうございました。
![スクリーンショット 2023-03-01 163042.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2854762/d7c3e8f6-f681-602b-4c93-052d765e48f7.png)

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


## 今回書いていくコード
・urls.py(お馴染み)
・views.py(お馴染み)
・detail.html(映画詳細のHTML)
・cast-detail.html(キャスト詳細のHTML)


## urls.py



urls.pyはこんな感じ
　　
```python
urlpatterns = [  
    path('detail/<int:id>', views.DetailCinemaView.as_view(),name='detail'),
    #映画詳細表示
    path('detailcast/<int:id>', views.DetailCastView.as_view(),name='cast'),
    #キャスト詳細表示
]

```

## views.py

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

　
```python
  
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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2854762/b5174979-f766-8abe-562e-c72925a09ee6.png)


映画詳細は↑

![スクリーンショット 2023-03-02 092143.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2854762/4b5102e0-0f78-6944-f31e-fce610079141.png)


キャスト詳細は↑

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



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

![スクリーンショット 2023-03-01 174815.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2854762/9ef81ce4-4bda-c73f-9514-28eaaa4b9ec9.png)

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

```python
cast_i = result["cast"]


crew_i = result["crew"]

```
　　

```python

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になったら終了させるようにしています。
キャストの顔写真は横スクロールも検討していますが、今回は取り急ぎの機能実装を心掛けてますので、このようにしております。


```python

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
#出演している映画のデータをとってきます。
```


　　

```python
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
　　

```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)でとってきたデータを
```python
        return render(request, 'app/detail.html', {
            'cinema_data': cinema_data,
            'cast_datalist': cast_datalist,
            'crew_datalist': crew_datalist
        })
```
のように返しておりますので、それぞれこのデータを{{}}と{%  %}で使い表示させるようにします。

## cast-detail.html
　　
```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)で辞書型に直すということも学べました。

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


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