※この記事はDjangoもくもく会: 4回目の成果発表です。
はじめに
叛逆のニジガサキってボーボボだったんだ... nikkieです。
Pythonには依存ライブラリ管理ツールが、たっくさんあります。
DjangoでWebアプリを作るときのツールの選択肢を増やしたく、素振りしました。
目次
前提:DjangoでWebアプリを作る
手前味噌ですが先日の記事から、DjangoでWebアプリを作る場合は「再配布しないプロジェクト」に当たります。
- ライブラリ(Djangoなど)のインストールが必要
- 開発しているプロジェクト自体はインストール可能にしない
プロジェクト自体をインストールしないという点について、依存ライブラリ管理ツール(Poetry, uv, Hatch)の理解を深めたく、今回Djangoを題材に素振りしました。
Djangoアプリは最小限でよいので、公式ドキュメントの投票アプリを作り始めた時点のものとしました。
ただし、SECRET_KEYを扱うためにdjango-environ1を導入しています2。
仮想環境を開発者が管理する場合
依存ライブラリ管理ツールを使わない場合です(すなわち、俺たちが依存管理ツールなんだ!3)。
Django公式ドキュメントやDjango Girls Tutorialはこの方法です。
venv-example/ ├── .venv/ ├── polls_tutorial/ │ ├── config/ # Djangoプロジェクト │ ├── polls/ # Djangoアプリケーション │ ├── .env # django-environ │ ├── db.sqlite3 │ └── manage.py ├── .python-version # Pythonはpyenvで管理 ├── requirements.in └── requirements.txt # pip-compile
好みで、pip-toolsを使いました4
% cd venv-example % source .venv/bin/activate % python -V Python 3.12.6 % cd polls_tutorial % python manage.py runserver

Poetry
過去の素振りから、pyproject.tomlでpackage-modeをfalseに指定します
[tool.poetry] name = "poetry-django-example" version = "0.1.0" package-mode = false
開発者の方でpython -m venv .venvしておき、この仮想環境をPoetryに使わせます(poetry install)。
poetry-example/ ├── .venv/ ├── polls_tutorial/ # Djangoプロジェクトとアプリケーション(変更がないので省略) ├── poetry.lock └── pyproject.toml
% cd poetry-example % poetry --version Poetry (version 1.8.2) % poetry run python -V Python 3.11.8 % cd polls_tutorial % poetry run python manage.py runserver

uv
uv 0.4.0からのuv init --appを使っていきます!5
これは「再配布しないプロジェクト」にドンピシャです。
pyproject.tomlは[build-system]を持ちません(想定通り)
[project]
name = "uv-django-example"
version = "0.1.0"
description = "Add your description here"
requires-python = ">=3.12"
dependencies = [
"django>=5.1.1",
"django-environ>=0.11.2",
]
uv-example/ ├── .venv/ # uvによる ├── polls_tutorial/ ├── .python-version # uvによる ├── pyproject.toml └── uv.lock
% cd uv-example % uv --version uv 0.4.12 (Homebrew 2024-09-18) % uv run python -V Python 3.12.5 % cd polls_tutorial % uv run python manage.py runserver

Hatch
今回挙げた中で一番動きが予想できなかったツール。
過去にも触っているので初見ではないのですが、「HatchはどんなPythonプロジェクトも一律インストールしてしまうのではないか」と私は認識していました。
- Pythonプロジェクトの管理ツール Hatch、私も、気になります! - nikkie-ftnextの日記
- 素振りの記:自分だけのクソライブラリ作りを通して、Hatchの機能に触れる - nikkie-ftnextの日記
- editable installしていた
Djangoの投票アプリのコードをコピーしてきてからhatch new --init。
hatch-example/ ├── polls_tutorial/ └── pyproject.toml # hatch new --init で生成
自動生成されたpyproject.tomlを修正しました。
全体は https://github.com/ftnext/django-project-examples/blob/6364c7b6228c2f92ebd67b4bd9e81237b7b7bd2a/hatch-example/pyproject.toml にあります
必要だったのは以下の指定。
[tool.hatch.build.targets.sdist] include = ["/polls_tutorial"]
これを書かずにhatch run python -Vとすると
ValueError: Unable to determine which files to ship inside the wheel using the following heuristics: https://hatch.pypa.io/latest/plugins/builder/wheel/#default-file-selection
Hatchはhatch_django_exampleディレクトリを探しますが、これが見つけられなかったために送出されたようです。
エラーメッセージの全文はこちら:https://github.com/pypa/hatch/blob/hatch-v1.12.0/backend/src/hatchling/builders/wheel.py#L235-L246
[tool.hatch.build.targets.wheel]の指定を案内されました。
偶然にもHatchで環境構築しているDjangoプロジェクト django-wiki を知っており、
https://django-wiki.readthedocs.io/en/latest/development/environment.html
そのpyproject.tomlを参考にしました。
関係ありそうに思えたのが、[tool.hatch.build.targets.sdist]。
https://github.com/django-wiki/django-wiki/blob/releases/0.11.2/pyproject.toml#L119-L127
[tool.hatch.build.targets.sdist]
include = [
"/src",
]
これにならって上記のように指定しました。
https://hatch.pypa.io/latest/config/build/#file-selection より「Patterns」にincludeやexcludeを指定する例があります(しっかり読んで理解深めたい)
以上で動かせています!
% cd hatch-example % hatch --version Hatch, version 1.12.0 % hatch run python -V Python 3.12.0 % cd polls_tutorial % hatch run python manage.py runserver

Hatchのことはまだよく分かっていないのですが、今回のDjangoアプリのコードはeditable installされていないかもしれません。
hatch shellで見えるパスのディレクトリ(site-packagesがある)を覗いたところ(過去のunkoの例とは違って)polls_tutorialのソースコードはeditable installされていないような??
終わりに
Djangoを使ったPythonプロジェクトを、俺たち / Poetry / uv / Hatch で環境構築しました。
- 俺たち=公式ドキュメントで案内される方法。仮想環境を用意する
- 今回は好みのpip-toolsを使ったよ
- Poetryとuv:Pythonプロジェクト自体をインストールしない設定が可能
- Poetryは
package-mode = false(pyproject.tomlの[tool.poetry]) uv init --app(pyproject.tomlに[build-system]が書かれない)
- Poetryは
- Hatchは
[tool.hatch.build.targets.sdist]を指定してhatch runからDjangoアプリを動かせた- Pythonプロジェクト自体はインストールされていない雰囲気(想定と違う。宿題事項)
ソースコードはこちらにあります
uvは簡単さがあると思います。
Poetryは独自仕様オレオレが強い6ので、この2つなら私はuv推し。
Hatchは簡単ではないのですが、私はまだ完全に理解していないようなので、引き続き小さなネタで手を動かしてみようと思います。
- 過去記事「Djangoの設定ファイルの分割について知りたく、書籍・記事を調査しました - nikkie-ftnextの日記」↩
-
DBはSQLiteで
.envでDATABASE_URL=sqlite:///db.sqlite3と指定するのですが、これによりmanage.pyを実行するカレントディレクトリにファイルが置かれるようです(実務寄りではPostgreSQLやMySQLのコンテナを用意すると思うので深追いしていません)↩ - ↩
- 公式ドキュメントのように直接インストールするよりも利点が多いので採用しています ↩
-
uv init --app --no-readme。できあがるhello.pyは不要なので削除しています↩ - 「PoetryはPEP 621をサポートしていない」↩