DjangoをRenderでデプロイする方法

DjangoをRenderでデプロイする方法

DjangoをRenderでデプロイする方法

この記事は部内での講習会用に作成された記事です。

今回はPaaSであるRenderを使ってDjangoアプリケーションをデプロイする方法について解説します。

以下が今回作成したアプリケーションのURLです。

好きな映画はミッションインポッシブルです。


Djangoアプリケーションの準備

まずはDjangoアプリケーションを準備します。
今回は外部APIを使用した簡単なWebアプリを作成していきます。

Djangoプロジェクトの作成

まずはDjangoプロジェクトを作成します。
今回はデプロイをするための仮想環境を使っていきます。

pythonでは仮想環境を作成するためにvenvというモジュールが標準で用意されています。

まずアプリを入れるディレクトリを作成します。
CLIで作成する場合は以下のコマンドを実行します。 

mkdir mymoviesapp

作成したらそのディレクトリに移動します。

cd mymoviesapp

次に仮想環境を作成します。

python -m venv venv

作成したら仮想環境を有効化します。

# Windowsの場合
venv\Scripts\activate
# Mac/Linuxの場合
source venv/bin/activate

仮想環境を有効化したらDjangoをインストールします。

pip install django
仮想環境ではローカルな環境と分離されるため、Djangoなどももう一度インストールする必要があります。これによって、必要なライブラリのみが入った環境を用意することができます

以下のコマンドを実行してDjangoプロジェクトを作成します。

django-admin startproject mymoviesapp .

manage.pyがあるディレクトリで、以下のコマンドでDjangoアプリケーションを作成します。

python manage.py startapp movies

アプリが作成されたら、settings.pyでアプリをプロジェクトに登録します。
以下のコードを追加します。

# mymoviesapp/settings.py
INSTALLED_APPS = [
    ...
    'movies', 
]

アプリのセットアップ

まずビューの準備をします。 以下のコードをmovies/views.pyに追加します。

# movies/views.py
from django.shortcuts import render
 
# Create your views here.
def home(request): 
    return render(request, "movies/home.html") 

次にURLの設定を行います。
まずMoviesディレクトリ内にurls.pyを作成します。
作成したら以下のコードを追加します。

# movies/urls.py
from django.urls import path
from .views import home
 
urlpatterns = [
    path("", home, name="home"),
]

URLを登録するためにmymoviesapp/urls.pyを以下のように編集します。

# mymoviesapp/urls.py
 
from django.contrib import admin
from django.urls import path, include
 
urlpatterns = [
    path("admin/", admin.site.urls),
    path("",  include("movies.urls")), 
]

次にテンプレートの準備をします。
まずはテンプレートディレクトリを作成します。
moviesディレクトリ内にtemplates/moviesディレクトリを作成します。

templatesディレクトリの配置に注意して作成してください!

作成したらhome.htmlを以下のように作成します。

<!-- movies/templates/movies/home.html -->
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>my movies app</title>
     <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body class="bg-dark text-white">
    <div class="container py-5 px-3 ">
        <h1>Movies Doc</h1>
    </div>
 
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script
</body>
</html>

これでアプリケーションの準備は完了です。

動作確認のために以下のコマンドを実行してサーバーを起動します。

python manage.py runserver

ブラウザでhttp://localhost:8000にアクセスすると、アプリケーションが表示されるはずです。


外部API「The Movie Database (TMDB)」を使ってみる

今回作成するアプリは外部APIを使用したアプリケーションです。
APIとは外部の組織が提供している機能を呼び出すだけで簡単に利用できる仕組みのことです。

今回使っていくAPIはThe Movie Database (TMDB)という映画情報を提供しているAPIです。
APIはチケットの役割を果たす
APIキー
を使って利用します。

TMDBのAPIkeyは無料でもらうことができます🎉
TMDBのAPIを使用するためにアカウント登録とAPIキーの取得をしていきます。


TMDBのアカウント登録とAPIキーの取得

  1. TMDBの公式サイトにアクセスします。
  2. 右上のTMDbに参加するをクリックしてアカウント登録を行います。
  3. アカウント登録が完了したら、右上のプロフィールアイコンをクリックして設定を選択します。
  4. メニューからAPIを選択します。
  5. ** API Keyを要求**をクリックしてAPIキーの申請を行います。
  6. フォームに必要な情報を入力してAPIキーを取得します。(テキトーでも大丈夫っぽい、、、)
  7. 取得したAPIキーをメモしておきます。(アクセストークンは今回は使用しません)
APIキーは他人に知られないように注意してください。APIキーが知られると他人に不正利用される可能性があります。Gitでアプリを管理する場合においてもgitignoreに登録しておきましょう。

TMDB APIを使うための準備

APIを使うためのチケットでありうるAPIキーを取得できたので、TMDB APIを使うための準備を行います。

まずAPIを使うためのkey情報をアプリ内に登録します。
このような情報は環境変数として登録するのが一般的です。

環境変数は**.env**というファイルを作成しそこにまとめて管理するのが一般的です。
.envをmanage.pyと同じディレクトリに作成します。

作成したら以下のようにAPIキーを登録します。

# .env
TMDB_API_KEY=取得したAPIキーをそのまま貼り付ける

この環境変数を読み込むためにpython-dotenvというライブラリを使用します。 以下のコマンドでインストールします。

pip install python-dotenv

次にsettings.pyで環境変数を読み込みます。

# mymoviesapp/settings.py
import os
from dotenv import load_dotenv
load_dotenv()  
TMDB_API_KEY = os.getenv("TMDB_API_KEY")  

これでsettings.pyでAPIキーを使用できるようになりました。


TMDB APIを使って映画情報を取得する

それでは実際にTMDB APIを使って映画情報を取得してみます。

今回は外部APIに触れるだけなので、詳しい使い方は割愛します。
TMDB APIのドキュメントはこちらにあります。

まずはデータを外部APIから取得するためのライブラリをインストールします。

pip install requests

コードをviews.pyに書いてもいいですが、今回はservices.pyというファイルを作成してそこにAPIを使うコードを書いていきます。

実はviews.pyの役割はあくまでテンプレートを返すことが主目的です。なのでロジックや実際の機能はservice.pyに分けることで可読性は機能の分割ができます。このような機能の分割を単一責任原則っていったり、、?

moviesディレクトリ内にservices.pyを作成します。 作成したら以下のコードを追加します。

import requests
from django.conf import settings
 
 
BASE_URL = "https://api.themoviedb.org/3"
 
def get_popular_movies():
    url = f"{BASE_URL}/movie/popular"
    params = {
        "api_key": settings.TMDB_API_KEY,
        "language": "ja-JP",
        "page": 1
    }
    res = requests.get(url, params=params)
    return res.json().get("results", [])

次にこのサービスをビューで使用します。
movies/views.pyを以下のように編集します。

# movies/views.py
from django.shortcuts import render
from .services import get_popular_movies 
 
 
def home(request):
    popular_movies = get_popular_movies() 
    print(popular_movies) 
    return render(request, "movies/home.html", {"popular_movies": popular_movies}) 

print文で取得したデータを確認できるので、ページを更新してみてください。

[{'adult': False, 'backdrop_path': '/1RgPyOhN4DRs225BGTlHJqCudII.jpg', 'genre_ids': [16, 28, 14, 53], 'id': 1311031, 'original_language': 'ja', 'original_title': '劇場版「鬼滅の刃」無限城編 第一章 猗窩座再来', 'overview': '鬼 となった妹・禰󠄀豆子を人間に戻すため鬼狩りの組織《鬼殺隊》に入った竈門炭治郎。入隊後、仲間である我妻善逸、嘴平伊 之助と共に様々な鬼と戦い、成長しながら友情や絆を深めていく。そして炭治郎は《鬼殺隊》最高位の剣士である《柱》と共に 戦い、「無限列車」では炎柱・煉󠄁獄杏寿郎、「遊郭」では音柱・宇髄天元、「刀鍛冶の里」では、霞柱・時透無一郎、恋柱 ・甘露寺蜜璃と共に激闘を繰り広げていった。その後、来たる鬼との決戦に備えて、隊士たちと共に《柱》による合同強化訓練 《柱稽古》に挑んでいる最中、《鬼殺隊》の本部である産屋敷邸に現れた鬼舞辻󠄀無惨。お館様の危機に駆けつけた《柱》た ちと炭治郎であったが、無惨の手によって謎の空間へと落とされてしまう。炭治郎たちが落下した先、それは鬼の根城≪無限城≫―”鬼殺隊”と”鬼”の最終決戦の火蓋が切って落とされる。', 'popularity': 631.4082, 'poster_path': '/tlNFKrkb0LzhnwvyiMSOoCB5dbj.jpg', 'release_date': '2025-07-18', 'title': '劇場版「鬼滅の刃」無限城編 第一章 猗窩座再来', 'video': False, 'vote_average': 7.682, 'vote_count': 292}, {'adult': False, 'backdrop_path': '/iZLqwEwUViJdSkGVjePGhxYzbDb.jpg', 'genre_ids': [878, 53], 'id': 755898, 'original_language': 'en', 'original_title': 'War of the Worlds', 'overview': 'ウィル・ラドフォードは、国土安全保障省のトップサイバーセキュリティアナリストです。大規模監視プログラムを通じて国家安全保障への潜在的な脅威を追跡しています。ある日、正体不明の組織による攻撃をきっかけに、政府が彼自身、 そして世界から何かを隠しているのではないかと疑念を抱くようになります。', 'popularity': 543.8486, 'poster_path': '/yvirUYrva23IudARHn3mMGVxWqM.jpg', 'release_date': '2025-07-29', 'title': 'ウォー・オブ・ザ・ワールド', 'video': False, 'vote_average': 4.33, 'vote_count': 553}, {'adult': False, 'backdrop_path': '/fq8gLtrz1ByW3KQ2IM3RMZEIjsQ.jpg', 'genre_ids': [27], 'id': 1038392, 'original_language': 'en', 'original_title': 'The Conjuring: Last Rites', 'overview': '', 'popularity': 323.8777, 'poster_path': '/29ES27icY5CzTcMhlz1H4SdQRod.jpg', 'release_date': '2025-09-03', 'title': '死霊館 最後の儀式', 'video': False, 'vote_average': 6.575, 'vote_count': 386}, {'adult': False, 'backdrop_path': '/wJ20rOZ1VgkCqv1jeOQB2Brny9k.jpg', 'genre_ids': [27, 9648], 'id': 1078605, 'original_language': 'en', 'original_title': 'Weapons', 'overview': '', 'popularity': 298.7871, 'poster_path': '/cpf7vsRZ0MYRQcnLWteD5jK9ymT.jpg', 'release_date': '2025-08-04', 'title': 'Weapons', 'video': False, 'vote_average': 7.389, 'vote_count': 1461}, {'adult': False, 'backdrop_path': '/mEW9XMgYDO6U0MJcIRqRuSwjzN5.jpg', 'genre_ids': [28, 53], 'id': 1007734, 'original_language': 'en', 'original_title': 'Nobody 2', 'overview': '', 'popularity': 295.2111, 'poster_path': '/svXVRoRSu6zzFtCzkRsjZS7Lqpd.jpg', 'release_date': '2025-08-13', 'title': 'M‥
obody 2', 'video': False, 'vote_average': 7.6, 'vote_count': 5}, ...]

こんな感じで大量の映画情報が取得できました🚀


映画情報をテンプレートに表示する

取得した映画情報はJSONというデータ形式の辞書のリストとして取得できます。
このデータはpythonの辞書型とリスト型に変換されています。

JSONについて詳しく知りたい方はこちらを参考にしてください。

このデータをテンプレートに表示していきます。
辞書型のリストなのでfor文などを使えばきれいに表示できそうです。

まずはテンプレートを以下のように編集します。

<!-- movies/templates/movies/home.html -->
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>my movies app</title>
     <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
 
<style> 
 
    .card:hover {
        transform: translateY(-5px);
        box-shadow: 0 10px 20px rgba(0,0,0,0.5);
        transition: transform 0.3s, box-shadow 0.3s;
        cursor: pointer;
    }
 
 
    .card {
        transition: transform 0.3s, box-shadow 0.3s;
    }
</style>
 
<body class="bg-dark text-white">
    <div class="container py-5 px-3 ">
        <h1>Movies Doc</h1>
 
        <div class="row row-cols-1 row-cols-sm-2 row-cols-md-3 row-cols-lg-5 g-4">
            {% for movie in popular_movies %}
            <div class="col">
                <div class="card h-100 bg-secondary text-white shadow-sm">
                    {% if movie.poster_path %}
                    <img src="https://image.tmdb.org/t/p/w500{{ movie.poster_path }}" class="card-img-top" alt="{{ movie.title }}">
                    {% else %}
                    <div class="bg-dark text-center p-5">No Image</div>
                    {% endif %}
 
                    <div class="card-body">
                        <h5 class="card-title">{{ movie.title }}</h5>
                        <p class="card-text small">{{ movie.overview|truncatechars:100 }}</p>
                    </div>
 
                    <div class="card-footer">
                        <small>公開日: {{ movie.release_date }}</small>
                    </div>
                </div>
            </div>
            {% endfor %}
        </div>
 
 
    </div>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script
</body>
</html>

これで映画情報を表示することができました!

これで一旦アプリケーションの方は完成です🎉


Renderでデプロイする

それではRenderでアプリケーションをデプロイしていきます。

まずはRenderのアカウントを作成します。(GitHubアカウントでOK) Renderの公式サイトにアクセスしてアカウントを作成してください。

requirements.txtの作成

Renderでアプリケーションをデプロイするために必要なライブラリをまとめたrequirements.txtを作成します。
これによってアプリに必要なライブラリをRenderが自動でインストールしてくれます。

今の内にこれから必要となるライブラリをインストールしておきます。

pip install gunicorn whitenoise
  • gunicorn: Djangoアプリケーションを本番環境で動作させるために使用されます。
  • whitenoise: 静的ファイルを効率的に配信するためのミドルウェアです。

以下のコマンドでrequirements.txtを作成します。

pip freeze > requirements.txt

これで必要なライブラリがrequirements.txtにまとめられました。
中身はこんな感じになっているはずです。

asgiref==3.9.1
certifi==2025.8.3
charset-normalizer==3.4.3
Django==5.2.6
gunicorn==23.0.0
idna==3.10
packaging==25.0
python-dotenv==1.1.1
requests==2.32.5
sqlparse==0.5.3
typing_extensions==4.15.0
tzdata==2025.2
urllib3==2.5.0
whitenoise==6.11.0

.envの設定

.envで環境の設定をしておきます。
ここでの.envは開発環境用の.envとして使用します。

本番環境用の.envはRenderのダッシュボードなどで設定します。

# .env
DEBUG=True
ALLOWED_HOSTS=127.0.0.1,localhost
TMDB_API_KEY=取得したAPIキーをそのまま貼り付ける

settings.puyの以下の内容を編集します。

# mymoviesapp/settings.py
...
DEBUG = os.getenv("DEBUG", "False") == "True"
ALLOWED_HOSTS = os.getenv("ALLOWED_HOSTS", "").split(",")
...

これで環境変数からDEBUGALLOWED_HOSTSを取得できるようになりました。

本番環境ではDEBUG = Falseにする必要があります。これを忘れるとセキュリティ上の問題が発生する可能性があります。Falseの設定はRenderのダッシュボードやGithub Secretsで行います。

静的ファイルの設定

Djangoアプリケーションを本番環境で動作させるために静的ファイルの設定を行います。
DjangoではCSSやJavascript、画像などの静的ファイルを管理するためにstaticfilesというアプリが用意されています。

settings.pyで以下のような記述を追加します。

# mymoviesapp/settings.py
...
MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "whitenoise.middleware.WhiteNoiseMiddleware", 
    "django.contrib.sessions.middleware.SessionMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django.contrib.messages.middleware.MessageMiddleware",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
]
 
...
 
STATIC_URL = "/static/"
STATIC_ROOT = BASE_DIR / 'staticfiles'
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

設定したら以下のコマンドを実行して静的ファイルを収集します。
実は開発環境でやる必要はないですが、本番環境では必須です。

python manage.py collectstatic --noinput
  • STATIC_ROOT: collectstaticコマンドで収集された静的ファイルが保存されるディレクトリを指定します。
  • STATICFILES_STORAGE: 静的ファイルの配信方法を指定します。ここではWhiteNoiseを使用して圧縮された静的ファイルを提供します。

これで作成したテンプレートがRender上で正しく表示されるようになります。


render.yamlの作成

Renderでアプリケーションをデプロイするためにrender.yamlを作成します。
これはRenderの設定ファイルで、アプリケーションのビルドやデプロイの方法を指定します。

以下のコードをrender.yamlとしてmanage.pyと同じディレクトリに作成します。

services:
  - type: web
    name: mymoviesapp
    env: python
    plan: free
    region: oregon
    buildCommand: |
      pip install -r requirements.txt
      python manage.py migrate
      python manage.py collectstatic --noinput
    startCommand: gunicorn mymoviesapp.wsgi:application
    autoDeploy: true
    envVars:
      - key: TMDB_API_KEY
        fromSecret: TMDB_API_KEY
      - key: DEBUG
        fromSecret: DEBUG
      - key: ALLOWED_HOSTS
        fromSecret: ALLOWED_HOSTS

これでDjangoの設定は完了です。 後はGitHubにプッシュしてRenderでデプロイするだけです。

GitHubにプッシュする

まずはGitHubにリポジトリを作成します。(publicにしてください)

リポジトリを作成したら以下のコマンドでGitの初期化を行います。

git init

次に**.gitignore**をmanage.pyと同じディレクトリに作成します。

# .gitignore
 
# Python
__pycache__/
*.py[cod]
*$py.class
 
# venv
venv/
 
# Django
*.sqlite3
/staticfiles/
media/
 
# Env
.env
.env.*
 
# VSCode
.vscode/
 
# PyCharm
.idea/
 
# Byte-compiled / cache
*.egg
*.egg-info/
.eggs/
*.manifest
*.spec
 
# MyPy
.mypy_cache/
 
# Pipenv / Poetry
Pipfile.lock
poetry.lock
 
# Logs
*.log
 
# macOS
.DS_Store
Thumbs.db

これでGitで管理しないファイルを指定できました。 次に以下のコマンドでコミットを行います。

git add .
git commit -m "Initial commit"
git branch -M main
git remote add origin https://github.com/{your-username}/your-repo.git # リポジトリのURLに置き換える
git push -u origin main

Renderでデプロイする

GitHubにプッシュしたらRenderのダッシュボードにアクセスします。

  1. RenderのダッシュボードでNewボタンをクリックしてWeb Serviceを選択します。
  2. Public Git RepositoryをクリックしてGitHubと連携します。
  3. デプロイしたいリポジトリのURLを入力します。
  4. LanguagePythonを選択します。
  5. Nameにアプリケーションの名前を入力します。(例: mymoviesapp)
  6. RegionOregonを選択します。(無料プランでは選択肢がこれしかない)
  7. Branchはmainを選択します。
  8. Build CommandStart Commandの値も一応入力しておきます
    • Build Command: pip install -r requirements.txt && python manage.py migrate && python manage.py collectstatic --noinput
    • Start Command: gunicorn mymoviesapp.wsgi:application
  9. Instance TypeはFreeを選択します。
  10. AdvancedをクリックしてEnvironment Variablesに以下の環境変数を追加します。
    • TMDB_API_KEY: 取得したAPIキー
    • DEBUG: False
    • ALLOWED_HOSTS: your-app-name.onrender.com (必ずRenderで表示されているURLにしてください)
  11. Deploy Web Serviceをクリックしてアプリケーションを作成します。

これでRenderが自動でアプリケーションをビルドしてデプロイしてくれます。 デプロイが完了したら、RenderのダッシュボードでアプリケーションのURLが表示されるので、そこにアクセスしてアプリケーションが正しく動作しているか確認してください。

デプロイには数分かかる場合があります。ビルドログで進行状況を確認できます。また無料枠なのでページを開くときに少し時間がかかってしまうことがあります。

これでDjangoアプリケーションをRenderでデプロイする方法の解説は終了です。
ちなみにRenderとGithubを連携しているので、GitHubにプッシュするたびに自動でデプロイされます。

502エラーが出た場合、ALLOWED_HOSTSの設定が間違っている可能性があります。Renderのダッシュボードで表示されているURLを正しく設定しているか確認してください。

他のStringを探す