[Mollbar]sqlite 3にリストフィールドを追加


背景:監督/俳優情報を映画データに追加
前文では、TMDB APIを介して映画データを取得し、DBに格納する方法を理解する.
今回は映画データの導入が決定したが、監督や俳優情報の追加導入が決定した.しかし、人気順で映画情報を取得するAPIには監督・俳優の情報はない.監督/俳優情報は独立したAPIで取得できる.
そこで、まず人気順に映画情報を取得し、その後、各映画のIDで再び監督/俳優情報APIに要求し、1つの情報を追加する.

def get_movie_datas():
    total_data = []
    BASE_URL = "https://api.themoviedb.org/3/movie/"

    # 1페이지부터 500페이지까지 (총 10,000개)
    for i in range(1, 501):
        request_url = f"{BASE_URL}popular?api_key={TMDB_API_KEY}&language=ko-KR&page={i}"
        movies = requests.get(request_url).json()
        
        for movie in movies['results']:
            # 개봉 날짜가 있는 영화의 데이터만 추가한다.
            if movie.get('release_date', ''):

                fields = {
                    'movie_id': movie['id'],
                    'title': movie['title'],
                    ...
                    'director': '',
                    'actors': [],
                }
                
                data = {
                    "pk": movie['id'],
                    "model": "movies.movie",
                    "fields": fields
                }

                total_data.append(data)
    
    # 감독/배우 정보가 있는 경우, 추가로 받아온다.
    for data in total_data:
        movie_id = data['fields']['movie_id']
        
        credit_request_url = f"{BASE_URL}{movie_id}/credits?api_key={TMDB_API_KEY}"
        credit_info = requests.get(credit_request_url).json()

        # 배우는 최대 10명까지만 저장한다.
        for cast in credit_info['cast'][:10]:
            data['fields']['actors'].append(cast['name'])
        
        if credit_info['crew']:
            data['director'] = credit_info['crew'][0]['name']

    with open("movie_data3.json", "w", encoding="utf-8") as w:
        json.dump(total_data, w, indent="\t", ensure_ascii=False)

get_movie_datas()
時間がかかりましたが、安全に情報を受け取ることができました.
質問:リストフィールドをsqlite 3に追加
現在、ムービーデータフィールドにはdirectoractorsが追加されているので、Movieモデルも2つのフィールドを追加する必要があります.directorは監督の名前なので、簡単にCharFieldを付けました.問題はactorsです.actors列には何人かの俳優の名前が入っています.したがって、リストを含むフィールドが必要です.ただし、PostgreSQLでは、リストを含むArrayFieldがサポートされていますが、sqlite 3にはArrayFieldはありません.
ソリューション:JSOnFieldの使用
幸いなことに、Django 3.1から(元々はPostgresqlしか使用できなかった)、JSONFieldも他のデータベースで使用できます.
Djangoの公式ドキュメントによると、sqlite 3でJSONFieldを使用するにはJSON 1拡張を有効にする必要があります.(JSON 1拡張を有効にする方法は、次のリンクで参照できます.)
関連リンクによると、MacOSはpython 3.7から、Windowsはpython 3.9からJSON 1 extensionがデフォルトでサポートされている.Windowsのオペレーティングシステムを使用しており、Python 3.9バージョンを使用しているので、設定を必要とせずにJSONFieldを直接使用することができます.

# movies/models.py

class Movie(models.Model):
    movie_id = models.IntegerField(unique=True)
    title = models.CharField(max_length=100)
    ...
    actors = models.JSONField(null=True)
    director = models.CharField(max_length=100, null=True)
リファレンスソース
https://docs.djangoproject.com/en/3.1/ref/models/fields/#django.db.models.JSONField
https://docs.djangoproject.com/en/3.2/ref/databases/
https://code.djangoproject.com/wiki/JSON1Extension