この記事は、Django Advent Calendar 2022 11日目の記事にしちゃいます(1/1に書いたので)。
Djangoに興味があるそこのあなた! よろしければ時を戻した投稿をしてみませんか?🎸
はじめに
歩夢だぴょん! あゆぴょんだぴょん!1
明けましておめでとうございます!
卯年ですね、nikkieです。
Python製Webアプリケーションフレームワークの1つ、Django(ジャンゴ)。
Djangoには設定ファイルがあり、これを分割できます。
「この分割は具体的にどうやるのか」を知りたく、文献調査しました。
分かったことをまとめます。
目次(=あたった文献リスト)
- はじめに
- 目次(=あたった文献リスト)
- 前提
- 暫定的な結論
- 初手『実践Django』
- 過去に見た資料 「本番運用を想定したDjango settings.pyの書き方入門」
- 脱線:分割した設定ファイルはどう指定する?
- 『Two Scoops of Django 3.x』 「5 Settings and Requirements Files」
- Two Scoops本が参照していた「The Best (and Worst) of Django」(2011)
- django-environ
- 小まとめ:環境ごとの設定を実現する2つの方法
- cookiecutter-django
- 終わりに
- P.S. その1 akiyokoさんの『現場で使える Django の教科書《基礎編》』では
- P.S. その2 設定ファイルの差分が見られる! diffsettings
前提
Djangoの設定ファイルとは
Django Girls Tutorialでは「プロジェクトを作成しよう!」の「設定変更」に設定ファイルについて記載があります。
django-admin startproject プロジェクト名 .
2すると、プロジェクト3が作られ、<プロジェクト名>/settings.py
も配置されます(詳しくはチュートリアルをどうぞ)。
このsettings.py
がこの記事で言う「設定ファイル」です4。
これの分割を考えていきます。
設定ファイルのドキュメントは以下です。
Djangoの設定 | Django ドキュメント | Django
この記事の前提
- 執筆者はDjangoを実務で使っていません。趣味開発5です
- 趣味開発のDjangoアプリの設定ファイルの分割についてハマってなんとか対処しました
- この経験で「設定ファイルの分割って分かってないな」と感じたので、自分の理解を深めるためにいくつかの文献にあたることにしました
- 深まった理解(次の趣味開発で採用する暫定的な結論)を元にアウトプットします
- もっといい方法をご存じの方はぜひ教えてください
- Djangoのバージョンは執筆時点で最新の4.1としてドキュメントを見ていきます
- 4.1はLTSではないので、今後リンク先のドキュメントが古くなっていくと思います。その場合はサポート中のバージョンで確認してください(LTSの4.2など)
暫定的な結論
- 次に作るDjangoアプリでは(
startproject
せずに)cookiecutter-django
を使う - すでに作ったDjangoアプリも設定ファイルを分割しているなら、
cookiecutter-django
に近づけたい
この結論に至った過程は以下をどうぞ!
初手『実践Django』
「9.9 設定ファイルの分割」というズバリなトピックがありました。
2つのやり方が紹介されています。
The Twelve-Factor App III. 設定
2についてはThe Twelve-Factor App6で推奨される方法として紹介されます。
Twelve-Factorは 設定をコードから厳密に分離すること を要求する。
なお、この“設定”の定義には、アプリケーション内部の設定は 含まない ことに注意する。
Twelve-Factor Appは設定を 環境変数 に格納する。
概要はつかめました。
具体的にどうやるのかを見ていきます。
過去に見た資料 「本番運用を想定したDjango settings.pyの書き方入門」
『Python実践レシピ』の著者の1人、筒井さんによる2021年のアウトプットです。
1.settings. pyを環境ごとに分ける(baseをimportして環境ごとに設定)2.秘密の値の環境変数からの読み取り、ImproperlyConfiguredを送出。3.ログ出力は標準出力のみ。cookiecutter-djangoで3つとも試せる。two scoop本3.0出た!
ブックマークコメントのうち、今回の調査トピックに関わってくるのは1と2ですね。
1について、settings.pyをsettings/base.pyとし、settingsディレクトリ下に環境ごとの設定ファイルを置きます。
settingsパッケージ導入というわけですね。
環境ごとの設定ファイルではfrom base import *
として共通の設定を読み込むのがポイント!(slide=18)
2について
- 秘密の値は環境変数から読み取る(slide=26)
os.environ
をラップし、必須の環境変数が設定されていなければImproperlyConfigured
を送出する関数で読み取る(slide=27 コードあります)- サードパーティライブラリ
django-environ
に言及(slide=28。この記事でも後述)
2の関数の実装については『Two Scoops of Django 3.x』が参照されています。
筒井さんの発表は記事版の寄稿もあります(2022年11月)。
脱線:分割した設定ファイルはどう指定する?
筒井さんのスライドにもありますが(slide=19)、複数の設定ファイルから1つを指定するやり方は2つあります。
django-admin と manage.py | Django ドキュメント | Django
もし複数の Django 設定ファイル間での切り替えが必要な場合は、django-admin を
DJANGO_SETTINGS_MODULE
もしくは--settings
オプションと共に利用してください。
Djangoの設定 | Django ドキュメント | Django
django-admin を使う場合、環境変数を予め指定しておくか、ユーティリティを起動する度に設定モジュールを明示的に渡します。
また、筒井さんのスライド(slide=22)では、manage.py
のデフォルトの設定をしている箇所を変更して、設定ファイル1つを指定しています。
ここで紹介した箇所には、環境ごとの設定ファイルが指定されます。
共通の設定であるsettings/base.py
は指定されません。
『Two Scoops of Django 3.x』 「5 Settings and Requirements Files」
筒井さんが参照していた 『Two Scoops of Django 3.x』も確認します。
「5 Settings and Requirements Files」での主張は以下かなと思います:
- 設定ファイル(秘密情報を除く)とrequirementsファイルはバージョン管理しよう
- 環境ごとに設定ファイルとrequirementsファイルを分割する方針
- 分割するが、DRYにする(繰り返さない)
- 筒井さんのスライドにあった共通の設定からのアスタリスクimport
- requirementsファイルでも適用できる(共通のrequirementsを作る)
- 秘密情報(
SECRET_KEY
10の設定値や、各種APIのキー)はバージョン管理しない- 環境変数
- 秘密情報をまとめたファイルから読み取る
1点目「バージョン管理しよう」から、「各自の開発環境にバージョン管理しないlocal_settings.py
を作る方法」はアンチパターンと紹介されます。
書きぶりからの推測ですが、過去にlocal_settings.pyを推していたが、少なくとも3.x版からは非推奨のようです。
3点目「秘密情報」の「環境変数」からの読み取りでは、筒井さんのスライドと同様の範囲がカバーされていました。
Two Scoops本が参照していた「The Best (and Worst) of Django」(2011)
The setup described here is based on the so-called “The One True Way”, from Jacob Kaplan-Moss’ The Best (and Worst) of Django talk at OSCON 2011. (p.45 5.2)
「The Best (and Worst) of Django」のスライド自体は Do the simplest thing that could possibly work. (Simon Willison) を繰り返し引用し、simpleなやり方を提案しています。
その中でlocal_settings.py
はアンチパターンと述べられています(slide=47)。
提案されるのが、上記のように、環境ごとに分割した設定ファイルを置く方法(The One True Way)です。
slide=47を見て、「バージョン管理しないlocal_settings.py
を置く方法」がどういう方法か分かりました。
local_settings.py
があればアスタリスクimportして、設定値を上書きするんですね。
try: from local_settings import * except ImportError: pass
django-environ
いくつかの文献で存在が紹介されているライブラリdjango-environ
を見てみましょう。
django-environ
is the Python package that allows you to use Twelve-factor methodology to configure your Django application with environment variables.
(意訳) django-environ
は、Djangoアプリケーションを環境変数で設定できるようにすることで、あなたがTwelve-factor方法論を使えるようにするPythonパッケージです。
上記リンク先のOverviewから引用します:
Using
django-environ
you can stop to make a lot of unversionedsettings_*.py
to configure your app.
(意訳) django-environ
を使うことで、アプリを設定するためにバージョン管理されていないたくさんのsettings_*.py
を作るのを止められます。
Quick Startに使い出しに必要な情報がまとまっています。
settings.py
は1つで、環境変数(.env
ファイルに定義)を複数作って切り替えるのがイメージできます。
小まとめ:環境ごとの設定を実現する2つの方法
ここまでの私の理解ですが、
- 設定ファイルはバージョン管理する(『Two Scoops of Django 3.x』)
- 方法1:設定ファイルの分割(「The Best (and Worst) of Django」)
- 環境ごとに設定ファイルができるが、DRYにしてファイルの多さに対処しているという理解
- 方法2:1つの設定ファイル + 環境変数で切り替え
- The Twelve-Factor Appで推奨される方法
django-environ
が可能にする- (完全に1つのファイルにはできないのではないか。後述)
cookiecutter-django
django-environ
のOverviewには次のようにあります。
See
cookiecutter-django
for a concrete example on using with a django project.
(意訳) Djangoプロジェクトで使う具体的な例については、cookiecutter-django
を見てください
というわけで見に行ってみましょう!
Cookiecutterとは、プロジェクトテンプレートからプロジェクトを作れるツールです(Python実装)。
Django用のテンプレートがcookiecutter-django
というわけですね。
Powered by Cookiecutter, Cookiecutter Django is a framework for jumpstarting production-ready Django projects quickly.
(意訳) Cookiecutter Djangoは、Cookiecutterを活かして、本番環境で動作できるブーストしたDjangoプロジェクトを素早く用意するためのフレームワークです。
今回は設定ファイルまわりに絞って見ます。
テンプレートの中の設定ファイルは以下にありました。
ディレクトリ構成
settings/ ├── __init__.py # 空。settingsパッケージにするために必要 ├── base.py # 共通設定。環境ごとの設定でアスタリスクimportされる ├── local.py # 開発環境用 ├── production.py # 本番環境用 └── test.py # テスト用
settings/base.pyを見ると、たしかにdjango-environ
を使った例になっています。
環境ごとの設定ファイルではbase.py
からdjango-environ
のオブジェクト(env
)をimportして設定の上書きをするなど、参考になるところは多いですね。
環境変数を使って設定をbase.py
に寄せつつも、1つの設定ファイルとなっていない理由の1つはINSTALLED_APPS
ではないかと思います。
例えばDjango Debug Toolbarは開発環境でだけ使いたいですよね。
INSTALLED_APPS
の設定は環境変数に寄せきれないから、大きな共通設定base.py
と、環境ごとの差分の設定というふうに分かれているのかなと思います。
小まとめの2つの方法のうち、なるべく方法2(1つの設定ファイル+環境変数)をやりつつ、できない部分は方法1(設定ファイルの分割)とするというハイブリッドな形なのかなと理解しました。
終わりに
「Djangoの設定ファイルの分割、具体的にどうやるのか」という疑問から文献調査をしました。
cookiecutter-django
、いいですね(django-environ
の思想、素晴らしい)。
Django Girls Tutorialで入門した頃は今ひとつよさが分かりませんでしたが、趣味開発でいくつかアプリを作り経験値が貯まったことで、設定ファイルの分割含めテンプレートのよさを認識できた感じです。
Djangoアプリのベストプラクティスを表しているとも思うので、素振りとして、cookiecutter-django
のテンプレートに採用されているまだ見ぬパッケージを触りに行くとDjango力が付きそうな印象です。
P.S. その1 akiyokoさんの『現場で使える Django の教科書《基礎編》』では
2018年の技術書典4版を参照しているので、最新版ではアップデートされている可能性が高いです11
local_settings.py
- 『Two Scoops of Django 3.x』では非推奨とされた方法
django-environ
を紹介
P.S. その2 設定ファイルの差分が見られる! diffsettings
https://docs.djangoproject.com/ja/4.1/ref/django-admin/#diffsettings
django-admin diffsettings
コマンドは
- 現在の設定ファイルと、Djangoのデフォルト設定
- 現在の設定ファイルと、指定した設定ファイル
の差分を表示するそうです。
複数の設定ファイルがあるときに気になるであろう差分も、簡単に確認できそうですね。
『Two Scoops of Django 3.x』5.6で存在を知りました。
-
↩明けましておめでとうございます🎍
— nikkie にっきー (@ftnext) 2022年12月31日
卯年🐰、フルバで言うと紅葉くん!
ここでニジガクの侑ちゃんから一言
「卯年、うさぎってことは、あ ゆ ぴ ょ ん!!」🤩🤩🤩 - https://docs.djangoproject.com/ja/4.1/ref/django-admin/#startproject↩
-
Djangoの用語として、プロジェクトは「Webアプリケーション全体の構成」を表します。実体はいくつかのファイルです(
__init__.py
が置かれるのでPythonパッケージになっています) ref: https://github.com/ftnext/2020_slides/blob/master/pycon_shizu_Feb_django_intro/parts/2-django_girls_tutorial/2-1_request_response.md↩ -
settings.py
はモジュールでもあるため、「設定モジュール」とも呼ばれていました。 ref: 「モジュールは Python の定義や文が入ったファイルです。ファイル名はモジュール名に接尾語 .py がついたものになります。」 6. モジュール — Python 3.11.0b5 ドキュメント↩ - レベル感のご参考まで 自作Djangoミニアプリ、テンプレートで頑張っていた検索フォームの実装をDjangoフォームで書き直しました - nikkie-ftnextの日記↩
- Twelve-Factor Appは方法論とのことです。「Twelve-Factor Appは、次のようなSoftware as a Serviceを作り上げるための方法論である。」↩
- この資料は2021年5月と10月の2つのバージョンがあります。ブックマークは1つ前のバージョンに対してですが、資料を見た限り内容的な差分はほとんどなさそうでした↩
- https://docs.djangoproject.com/ja/4.1/topics/settings/#envvar-DJANGO_SETTINGS_MODULE↩
- https://docs.djangoproject.com/ja/4.1/ref/django-admin/#cmdoption-settings↩
-
Djangoの設定ファイルの中の
SECRET_KEY
は暗号署名に使われます。詳しくは 暗号署名 | Django ドキュメント | Django をどうぞ↩ - 「設定ファイルについて大幅加筆(第10章)」 ref: これぞベスト・オブ・Django 本!『現場で使える Django の教科書《基礎編》』が Kindle で販売中 - akiyoko blog↩