Django初心者が知っておきたい `settings.py` の基本構成と役割

## ０．はじめに
Djangoでアプリ開発を始めると、必ず目にするのが `settings.py`。
けれど、中身が多すぎて「どこを触っていいのか分からない」と感じる方も多いのではないでしょうか。

また、開発を進めていくうちに「メール送信をしたい」「ログイン後の遷移先を指定したい」「本番ではセキュリティ設定を強化したい」といった場面が訪れ、`settings.py`の修正や追加は避けて通れなくなります。
実際、私自身もToDoアプリを本番環境にデプロイする過程で、必要な設定項目が次々と増えていくのを実感しました。

本記事では、私自身が開発・本番デプロイを通じて構築したToDoアプリの `settings.py` をベースに、以下の点を丁寧に解説します。
- **よく使う設定項目とその意味**
- **開発環境と本番環境の切り替え方法**
- **セキュリティやログの設定まで含めた実践的な使い方**

「設定ファイルの構造を理解して、安全で運用しやすいアプリにしたい」という方にとって、一つの指針になればと思います。

## １．`settings.py` とは何か？
`settings.py` は、Djangoプロジェクト全体の「構成と振る舞い」を定義する中心的な設定ファイルです。  
言い換えれば、アプリケーションの**環境変数、ミドルウェア、テンプレート、静的ファイル、セキュリティポリシーなどの一元管理ハブ**として機能します。

このファイルに定義された内容は、Djangoの内部処理のあらゆる場面で参照されており、設定次第でアプリケーションの挙動は大きく変わります。

以下の章でそれぞれの役割について解説します。

## ２．プロジェクトの基礎構成と環境変数の導入
この章では、`settings.py` の冒頭で定義される **パス構成** や **環境変数の読み込み** に関する基本的な設定について解説します。

アプリを安全かつ柔軟に運用するためには、以下のような初期設定が重要になります：

- プロジェクト全体のディレクトリ構成を見失わないようにすること
- 開発環境と本番環境の違いに応じて挙動を切り替える仕組みを持つこと
- 秘密情報をソースコードから切り離し、環境ごとに設定できるようにすること

こうした基礎を丁寧に押さえておくことで、後続の設定（テンプレート、静的ファイル、セキュリティ設定など）がより整理された形で構築できるようになります。
### （１）`BASE_DIR`：プロジェクトの基準ディレクトリ
`BASE_DIR` は、`settings.py` を基準にしたパス操作のための変数です。
`BASE_DIR / 'templates'` や `BASE_DIR / 'static'` のように使うことで、相対パスでのファイル指定を明確かつ安全にできます。（以降の章にもそのように記載している箇所があります。）
```settings.py
import os
from dotenv import load_dotenv
from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent
```

### （２）`.env`と `load_dotenv()` の活用
`python-dotenv` パッケージを使って `.env` ファイルを読み込んでいます。
これにより、以下のようなセキュアで柔軟な運用が可能になります：
- 秘密鍵やメール認証情報などをコードベースに残さない
- 環境（開発・本番）ごとに切り替えがしやすい
- `.gitignore` に `.env` を追加して、Gitに上げない運用
```settings.py
load_dotenv(dotenv_path=BASE_DIR / '.env')
```

### （３）`DEBUG` の分岐
`.env` に `DJANGO_DEBUG=True` を記載すれば開発モードで起動、未指定や `False` なら本番モードとして動作します。
これにより、同じコードベースでも環境に応じて挙動を切り替えられます。
```settings.py
DEBUG = os.environ.get('DJANGO_DEBUG', 'False') == 'True'
```

### （４）`SECRET_KEY` の管理
本番環境では `SECRET_KEY` を `.env` に記述し、開発中はベタ書きで対応する構成です。
こうすることで、以下のような設計上のバランスを取っています：
- 開発環境ではすぐ動く
- 本番環境では機密情報が外部に漏れない
- 設定ミスによる500エラー（SECRET_KEY未指定）も防げる
```settings.py
DEBUG = os.environ.get('DJANGO_DEBUG', 'False') == 'True'
if DEBUG:
    SECRET_KEY = 'django-xxx'
else:
    SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY')
```
このように、プロジェクトの入り口部分で パス構成・セキュリティ・環境切替の基盤 を整えておくことで、後続の設定がシンプルかつ柔軟に進められるようになります。

## ３．本番環境で必須のセキュリティ設定
本番環境にデプロイしたDjangoアプリを安全に運用するためには、いくつかの明示的なセキュリティ設定が必要になります。ここでは `ALLOWED_HOSTS` や `CSRF_TRUSTED_ORIGINS`、そしてHTTPS対応のための設定について解説します。

### （１）`ALLOWED_HOSTS`について
Djangoでは、本番環境で受け入れるリクエストの「ホスト名（ドメイン/IP）」を明示的に設定する必要があります。
未設定のままだと、本番でアクセスした際に `DisallowedHost` エラーが発生します。

特に以下のようなケースに注意が必要です：
- `example.com` だけでなく `www.example.com` もアクセス対象にする場合は、両方を記載する必要あり
- AWS EC2のElastic IPを使ってアクセス確認する場合、そのIPも明記する必要あり
**開発段階ではワイルドカード `['*']` が使えますが、本番では厳禁です。**
意図しないドメインからのアクセスも許可してしまい、セキュリティ上のリスクになります。

```settings.py
ALLOWED_HOSTS = [
    'example.com',        # 独自ドメイン
    'www.example.com',    # www付きの場合
    'xxx.xxx.xxx.xxx',    # Elastic IP
    'localhost',          # ローカル環境の確認用
    'xxx.xxx.xxx.xxx',    # ローカルIP（ローカルテスト用）
]
```

### （２）`CSRF_TRUSTED_ORIGINS`について
クロスサイトリクエストフォージェリ（CSRF）対策として、Djangoでは「信頼できる送信元のスキーム付きドメイン」を指定する必要があります。

以下のようなケースで特に必要になります：
- HTTPSを有効にしている
- HTMLフォームやAjaxリクエストで POST する画面がある
- ブラウザが「クロスオリジン」扱いする条件下で、403エラーが発生する

設定をしないと、ログイン・登録・フォーム送信などがCSRF検証で拒否される可能性があります。
http://〜 ではなく、必ず https://〜 の形式で指定する必要があります（スキーム付き）。
```settings.py
CSRF_TRUSTED_ORIGINS = ['https://example.com', 'https://www.example.com']
```
※`ALLOWED_HOSTS`と異なり、`CSRF_TRUSTED_ORIGINS`では `['*']` のようなワイルドカード指定はできません。

### （３）HTTPS対応を行う場合
さらにHTTPS対応を行う場合は下記を追加します。
- `SECURE_SSL_REDIRECT`：HTTPアクセス時にHTTPSへリダイレクト
- `SESSION_COOKIE_SECURE`：セッションクッキーをHTTPS通信時のみ送信
- `CSRF_COOKIE_SECURE`：CSRFトークンクッキーもHTTPSのみ送信
- `SECURE_HSTS_SECONDS`：HSTSヘッダーで、HTTPS通信をブラウザ側に強制（秒数単位）
- `SECURE_HSTS_INCLUDE_SUBDOMAINS`：サブドメインにもHSTSを適用

特に `SECURE_SSL_REDIRECT = True` を設定しておかないと、**意図せずHTTP経由でアクセスされてしまいセッションが乗っ取られるリスク**があります。

なお、これらの設定を有効にしても、サーバー側でHTTPS証明書が未設定の場合は動作しないため、**nginxやALB側でのSSL対応も併せて実施**する必要があります。

このように、セキュリティ関連の設定は「後回し」にしがちですが、**本番環境においては最優先で構成すべき項目**です。
また、`.env` にフラグを持たせて動的に切り替えることで、開発時の利便性と本番時の安全性を両立できます。
```settings.py
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_HSTS_SECONDS = 31536000
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
```

## ４．アプリケーション構成の管理
Djangoでは、Webアプリケーションを構成するさまざまな要素を `settings.py` 上で明示的に定義します。  
この章では、プロジェクトにおけるアプリの登録・リクエスト処理の流れ・URLルーティングの基点について見ていきます。

### （１）`INSTALLED_APPS`について
Djangoでは、アプリ単位で機能を分けて開発するのが一般的です。`INSTALLED_APPS` に記載することで、そのアプリが有効（読み込み対象）であることをDjangoに伝えます。上から順に読み込まれるため、依存関係がある場合は順序も意識すると良いです。
- `users`, `todos` は自作アプリ（ `apps.py` で設定した名前）です。
- `widget_tweaks` のように外部パッケージを追加する場合もここで登録が必要です。
- `django.contrib.*` 系はDjangoの基本機能（認証、管理画面、セッションなど）に相当します。
```settings.py
INSTALLED_APPS = [
    'users.apps.UsersConfig',
    'todos.apps.TodoConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'widget_tweaks',
]
```

### （２）`MIDDLEWARE`について
`MIDDLEWARE` は、リクエストやレスポンスに介入する“中間処理”の一覧です。認証、セッション、CSRF検証、セキュリティヘッダーなど、あらゆる処理がここで定義されています。順序が重要であり、入れ替えたり削除すると動作に影響が出ます。

API開発では `CorsMiddleware`（CORS対応）などを追加することがあります。
エラーログ収集やモニタリング用途で独自のMiddlewareを挟むこともあります。

```settings.py
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    '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',
]
```

### （３）`ROOT_URLCONF`・`WSGI_APPLICATION`について
- `ROOT_URLCONF`
    - プロジェクト全体のURLルーティングのエントリーポイントを指定します。
    - `config/urls.py` にルーティング処理を集約する構成です。
    - ここで各アプリのURLに include() を使って振り分けます。
- `WSGI_APPLICATION`
    - WSGI（PythonのWebサーバーゲートウェイインターフェース）のエントリーポイントです。
    - 本番環境でGunicornやuWSGIなどからDjangoアプリを起動する際に参照されます。
    - `config.wsgi.application` は `config/wsgi.py` 内の `application` オブジェクトを指しています。

```settings.py
ROOT_URLCONF = 'config.urls'
WSGI_APPLICATION = 'config.wsgi.application'
```

これらの設定は普段あまり変更しない部分ではありますが、開発が進むにつれて拡張や修正が必要になることも多いため、構造を理解しておくことが重要です。

## ５．テンプレートと静的ファイルの設定
Djangoでは、HTMLテンプレートやCSS/JavaScriptといったフロントエンドの要素も `settings.py` で適切に設定しておく必要があります。  
ここでは、テンプレート読み込み設定と静的ファイルの扱いについて解説します。

### （１）`TEMPLATES` について
- `DIRS`：`BASE_DIR / 'templates'`でプロジェクト直下の共通テンプレートディレクトリを指定
- `APP_DIRS`：`True` にすることで、各アプリ配下の `templates/` ディレクトリも自動検出される
- `context_processors`：テンプレート内で使える変数を自動で追加する仕組み（ログインユーザー情報など）
プロジェクト内で共通のレイアウト（例：`base.html`）を使う場合は、`templates` ディレクトリをプロジェクト直下に作成し、`DIRS` に明示するのが一般的です。
一方、アプリ個別の画面はアプリごとの `templates/app名/ファイル名.html` に配置すると、アプリ分離が保たれます。

```settings.py
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR / 'templates'],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]
```

### （２）`STATIC_URL`・`STATICFILES_DIRS`・`STATIC_ROOT` について
- `STATIC_URL`：静的ファイル（CSS/JS/画像など）を参照する際のURLパス。テンプレート内で `{% static 'style.css' %}` のように使われる。
- `STATICFILES_DIRS`：開発時に参照する静的ファイルのディレクトリを指定。ここで指定したパス内のファイルは自動で対象になる。通常は `BASE_DIR / 'static'` を指定してプロジェクト全体の共通静的ファイルをまとめる。
- `STATIC_ROOT`：本番環境で `python manage.py collectstatic` を実行したときに、すべての静的ファイルがここに集約される。NginxなどのWebサーバーがこのディレクトリを参照して配信する。

```settings.py
STATIC_URL = 'static/'
STATICFILES_DIRS = [BASE_DIR / 'static']
STATIC_ROOT = BASE_DIR / 'staticfiles'
```

開発中（`runserver`）では `STATICFILES_DIRS` から直接読み込みますが、本番環境では `collectstatic` によってファイルを `STATIC_ROOT` に集約し、NginxなどのWebサーバーから配信します。
この仕組みを理解していないと「本番でCSSが反映されない」といったトラブルにつながるので、あらかじめ構造を把握しておくと安心です。

## ６．認証・ログイン導線の整理
Djangoにはデフォルトで認証機能が組み込まれており、ログイン／ログアウト／ユーザー登録などの導線を整備するためには、`settings.py` にいくつかの明示的な設定を追加しておく必要があります。

以下の設定によって、**認証処理後の遷移先や、ログインが必要なページにアクセスした際の挙動**がコントロールされます。
- `AUTH_USER_MODEL`：使用するユーザーモデルをカスタムモデルに切り替える
- `LOGIN_REDIRECT_URL`：ログイン成功後のリダイレクト先を指定する
- `LOGIN_URL`：ログインが必要なページにアクセスした際のログイン画面のURLを指定する
- `LOGOUT_REDIRECT_URL`：ログアウト後にリダイレクトするURLを指定する

```settings.py
AUTH_USER_MODEL = 'users.CustomUser'
LOGIN_REDIRECT_URL = '/'
LOGIN_URL = '/login/'
LOGOUT_REDIRECT_URL = '/login/'
```
認証導線を明確にしておかないと、「ログイン後にどこにも遷移せず404になる」といった初学者トラブルが起きやすいです。

これらの設定はすべて `urls.py` や `views.py` と密接に関係するため、設定→URL→画面遷移の流れをセットで把握することが重要です。

## ７．メール送信設定
Djangoでは、パスワードリセットや通知機能を実装する際にメール送信が必要になります。  
`settings.py` にて、環境（開発／本番）に応じて送信方法やSMTPサーバーを適切に設定することで、**安全かつ実用的なメール運用**が可能になります。

- 開発用：`EMAIL_BACKEND = 'console.EmailBackend'`
    - メール送信の代わりに **コンソールに内容を出力するモード**
    - 実際にはメールは送られず、内容を開発者が確認できる
    - セキュリティリスクがない・すぐに確認できる・設定が簡単 という利点あり
- 本番用
    - `EMAIL_BACKEND`：Djangoが使用するメール送信手段（例：SMTPやコンソール出力）を指定する  
    - `EMAIL_HOST`：利用するSMTPサーバーのホスト名（例：smtp.gmail.com）を指定する  
    - `EMAIL_PORT`：SMTPサーバーに接続するためのポート番号を指定する（通常587または465）  
    - `EMAIL_HOST_USER`：SMTP認証時に使用するユーザー名や送信元メールアドレス  
    - `EMAIL_HOST_PASSWORD`：SMTP認証に使用するパスワードやAPIキー（.envで管理推奨）  
    - `EMAIL_USE_TLS`：SMTP通信をTLSで暗号化するかどうかの設定（Trueが推奨）  
    - `DEFAULT_FROM_EMAIL`：メールの送信元として表示されるデフォルトのアドレス

```settings.py
if DEBUG:
    # 開発用
    EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
else:
    # 本番用
    EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
    EMAIL_HOST = os.environ.get('DJANGO_EMAIL_HOST')
    EMAIL_PORT = int(os.environ.get('DJANGO_EMAIL_PORT', 587))
    EMAIL_HOST_USER = os.environ.get('DJANGO_EMAIL_USER')
    EMAIL_HOST_PASSWORD = os.environ.get('DJANGO_EMAIL_PASSWORD')
    EMAIL_USE_TLS = True
    DEFAULT_FROM_EMAIL = os.environ.get('DEFAULT_FROM_EMAIL', 'noreply@example.com')
```
この構成にしておくことで、開発時の利便性と、本番での安全な運用の両方を実現できます。

## ８．ログ出力の設定
本番運用を見据えたDjangoアプリケーションでは、**エラーや重要な処理のログをファイルに記録する設定**を行うことが重要です。  
ここでは、標準的なログ出力構成を紹介します。Djangoのログ機能は Python 標準の `logging` モジュールに準拠しており、細かいカスタマイズも可能です。

- `version`：ログ設定のバージョン。常に `1` を指定する（Pythonの `logging` モジュールの仕様）
- `disable_existing_loggers`：既存のロガーを無効化するかどうか。`False` にするとDjangoのデフォルトロガーが維持される
- `formatters`：ログの出力フォーマットを定義する（例：`verbose` や `simple` など）
- `handlers`：ログの出力先や出力方法を定義する（この例ではログをファイルに出力）
- `loggers`：どのロガーがどのハンドラを使い、どのレベルで出力するかを指定する（ここではDjangoアプリのログをファイル出力）
```settings.py
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': '{levelname} {asctime} {module} {message}',
            'style': '{',
        },
        'simple': {
            'format': '{levelname} {message}',
            'style': '{',
        },
    },
    'handlers': {
        'file': {
            'level': 'INFO',
            'class': 'logging.FileHandler',
            'filename': BASE_DIR / 'django.log',
            'formatter': 'verbose',
        },
    },
    'loggers': {
        'django': {
            'handlers': ['file'],
            'level': 'INFO',
            'propagate': True,
        },
    },
}
```
このように、最小限の構成でもログ出力の基盤が整備されることで、**本番運用における“見える化”と“トラブル対応力”を高める**ことができます。

## ９．おわりに
ここまで、Djangoの `settings.py` における主要な設定項目を、開発から本番運用までの視点で解説してきました。
設定ファイルの構造や意味をしっかり押さえておくことで、**プロジェクトの成長や運用フェーズに応じた拡張・変更にも柔軟に対応できるようになります**。

「参考になった！」と思ったらいいねしていただけると励みになります！
また、気になる点があればコメントで教えていただけると嬉しいです。