Django: settings.py
目次

概要

  • 設定オブジェクト: django.conf.settings

    • Django 起動時に次のようにインスタンス化されるシングルトンなグローバルオブジェクト

      # django/conf/__init__.py
      settings = LazySettings()
      
    • ↑ は、Django のデフォルト設定ファイル ( django.conf.global__settings.py ) を読み込んだ後

    • プロジェクト作成時に生成される設定ファイル ( settings.py ) を読み込んで設定を上書きされる

  • 設定ファイル: プロジェクト生成時に生成される settings.py

    • Django のデフォルト設定とは異なるプロジェクト固有の設定値や

    • 自作のアプリケーションで利用する独自の変数を記述しておく

  • Django で利用できる設定変数とそのデフォルト値の一覧 => https://docs.djangoproject.com/ja/2.2/ref/settings/

  • View や models からアクセスするときは、オブジェクトなので、

    # こんな風に参照しましょう
    from django.conf import settings
    settings.LOGIN_URL
    
  • LazySettings ??

    • その設定値にアクセスされてから初めてその属性が読み込まれる

    • 最初にその属性値にアクセスされるまでは設定を変え放題

    • settings の属性に一度でもアクセスされてしまうと、変更しようとしてもエラーになるので、

    • 基本的には、設定ファイルの中で初期設定を済ませよう

インストールするアプリケーション一覧

INSTALLED_APPS = [
    # 略
    # Install するアプリケーションをリスト形式で列挙
    # 各アプリディレクトリ.apps.py の AppConfig クラスのサブクラスを指定する
    'accounts.apps.AccountsConfig',
    'shop.apps.ShopConfig',
]
  • パッケージ名を書くのは少し古い書き方

  • 上に書いた方が優先順位が高い

デバッグ設定

DEBUG = False
  • 開発時は True にしておくと、いろいろ便利

    • エラー発生時に画面にデバッグ情報が出力される

    • django-debug-toolbar, SQL 文のロギングは True じゃないと使えない

静的ファイル/メディアファイル

静的ファイル関連の設定

  • 静的ファイル (static ファイル): リクエストに応じて中身を変更せずそのまま配信するファイル

    • CSS ファイル

    • JavaScript ファイル

    • 画像ファイルに

  • 単に静的ファイルをブラウザへ返すだけの処理をアプリケーションサーバーで捌くと、無駄が多くなってしまう

    • => アプリケーションサーバーの前段に Nginx に代表される リバースプロキシ と呼ばれるサーバーを配置し、

    • => 静的ファイルを返すだけの処理はリバースプロキシが担当し、

    • => Web application の処理が必要なリクエストだけをアプリケーションサーバーへ振り分けることで、

    • => 効率よくリクエストを捌けるようにする

  • セキュリティの観点から、↓は別々にするケースが多い

    • 静的ファイルの配信元

    • プロジェクトで静的ファイルをバージョン管理する際のプロジェクト内での置き場所

  • 最低限↓の3つの設定必要

    # これしておくと便利
    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    PROJECT_NAME = os.path.basename(BASE_DIR)
    
    # 静的ファイル配信用のディレクトリ、URL の一部になる
    # 設定値はデフォルトの `/static/` のままでよい
    STATIC_URL = '/static/'
    
    # アプリケーションに紐づかない静的ファイルの置き場
    STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
    
    # 静的ファイルの配信元
    # collectstatic コマンドで静的ファイルを集約する際のコピー先でもある
    # `STATICFILES_DIRS` とは別のディレクトリを指定する必要がある
    # DEBUG = False のときに必要
    STATIC_ROOT = '/var/www/{}/static'.format(PROJECT_NAME)
    
  • 静的ファイル集約のための管理コマンド: collectstatic

    $ python3 manage.py collectstatic
    
    • DEBUG = True のときは、 runserver がやってくれるので自分で collectstatic する必要ない

  • STATIC_URL を使って画像を表示するテンプレート実装例

    {% load static %}
    <img src="{% static 'shop/images/no-image.png' %}">
    <img src="{% static 'images/logo.png' %}">
    

メディアファイル関連設定

  • メディアファイル: 静的ファイルのうち、 (システム管理者を含めた) ユーザーがサイトを利用してアップロードするファイル

  • 本番環境では、メディアファイルもAPサーバーで裁かずにリバースプロキシなどで捌くことで負荷を減らす

# メディアファイルの設定例 (config/settings.py)
# DEBUG =  False 時
MEDIA_URL = '/media/'
MEDIA_ROOT = '/var/www/{}/media'.format(PROJECT_NAME)

# ユニットテスト時 or PaaS ? WhiteNoise 時
MEDIA_ROOT = os.path.join(BASE_DIR, 'media_root')
  • アップロードを実装するときのコツは P.114 付近に詳しく書いてあるので、実装するときはよく見ること

runserver でメディアファイルを配信してくれる仕組みがある

動作確認に便利

# config/urls.py
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    # ...
]
# static 関数の内部で DEBUG = True でないと動作しないようにチェックしているよ
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

データベース設定

組み込みでサポートしているデータベースエンジン:

  • django.db.backends.postgresql (PostgreSQL)

  • django.db.backends.mysql (MySQL)

  • django.db.backends.sqlite3 (SQLite)

  • django.db.backends.oracle (Oracle)

設定できる項目一覧:

  • https://docs.djangoproject.com/ja/2.2/ref/settings/#databases

    • ATOMIC_REQUESTS: トランザクションの有効範囲をリクエストの開始から終了までにするかどうかを指定できる

    • OPTIONS:

      • いろんなオプションを設定できる

        • トランザクションの分離レベル isolation_level

        • MySQL の SQL モード sql_mode など

      • デフォルトから変更したら、Django 側だけでなくデータベース側にも同じ設定をしておくのが望ましい

MySQL で注意する点:

  • SQLモードを「厳密モード」にしておかないと振る舞いが微妙なので、設定しておいたほうがよい

    # 最も厳しく設定するとこうなる
    'OPTIONS': {
        'sql_mode': 'TRADITIONAL,NO_AUTO_VALUE_ON_ZERO'
    }
    
  • MySQL を利用する際はドライバーが必要: Django 推奨は mysqlclient

ロギングの設定

https://docs.djangoproject.com/ja/2.2/topics/logging/

  • プロジェクト作成時にはロギング設定は書かれていない

  • Django の起動時に django.utils.log.py の DEFAUT_LOGGING の設定が読み込まれる

本番稼働時の LOGGING 設定例

LOGGING = {
    # バージョンは「1」固定
    'version': 1,
    # 既存のログ設定を無効化しない
    'disable_existing_loggers': False,
    # ログフォーマット
    'formatters': {
        # 本番用
        'production': {
            'format': '%(asctime)s [%(levelname)s] %(name)s %(process)d %(thread)d '
            '%(pathname)s %(lineno)d %(message)s'
        },
    },
    # ハンドラ
    'handlers': {
        # ファイル出力用ハンドラ
        'file': {
            'level': 'INFO',
            # logging.handlers.RotatingFileHandler, logging.handlers.TimeRotatingFileHandler
            # を使うとログファイルをローテーションできて便利
            'class': 'logging.FileHandler',
            'filename': 'var/log/{}.log'.format(PROJECT_NAME),
            'formatter': 'production',
        },
    },
    # ロガー
    'loggers': {
        # 自作アプリケーション全般のログを拾うロガー
        # '' と書くと、独自に追加したアプリケーションのログを拾うことができる
        '': {
            'handlers': ['file']
            'level': 'INFO',
            'propagate': False,
        },
        # Django 本体が出すログ全般を拾うロガー
        'django': {
            'handlers': ['file']
            'level': 'INFO',
            'propagate': False,
        },
    },
}

開発時の LOGGING 設定例

LOGGING = {
    # バージョンは「1」固定
    'version': 1,
    # 既存のログ設定を無効化しない
    'disable_existing_loggers': False,
    # ログフォーマット
    'formatters': {
        # 開発用
        'develop': {
            'format': '%(asctime)s [%(levelname)s] %(pathname)s %(lineno)d %(message)s'
        },
    },
    # ハンドラ
    'handlers': {
        # コンソール出力用ハンドラ
        'console': {
            'level': 'DEBUG',
            # logging.handlers.RotatingFileHandler, logging.handlers.TimeRotatingFileHandler
            # を使うとログファイルをローテーションできて便利
            'class': 'logging.StreamHandler',
            'filename': 'var/log/{}.log'.format(PROJECT_NAME),
            'formatter': 'develop',
        },
    },
    # ロガー
    'loggers': {
        # 自作アプリケーション全般のログを拾うロガー
        '': {
            'handlers': ['console']
            'level': 'DEBUG',
            'propagate': False,
        },
        # Django 本体が出すログ全般を拾うロガー
        'django': {
            'handlers': ['console']
            'level': 'INFO',
            'propagate': False,
        },
        # 発行される SQL 文を出力するための設定
        # パフォーマンスの観点から DEBUG = True でないと出力されないようになっている
        'django.db.backends': {
            'handlers': ['console']
            'level': 'DEBUG',
            'propagate': False,
        },
    },
}

ロガーを取得する

logger = logging.getLogger(__name__)

その他の重要な設定

ベストプラクティス

  • 個人の開発環境の設定は local_settings.py に書く

    $ python3 manage.py runserver 0.0.0.0:8000 --settings config.local_settings
    
    # もしくは
    $ export DJANGO_SETTINGS_MODULE=config.local_settings
    $ python3 manage.py runserver 0.0.0.0:8000
    
  • シークレットな変数は .env に書く

    • バージョン管理下に置かない

    • settings.py には書かない

    • django-environ 便利