- 公式ドキュメント Django の新しいバージョンへの更新 で推奨されていることを実施しましょう。
- django-upgrade を使うと対応したバージョンに自動で対応できます。
- 使用しているPythonやデータベースが移行対象のDjangoで使用できない場合、同時もしくは先んじて対応が必要です。
- CI環境を整備して、継続してバージョンアップしやすい環境を保ちましょう。
- サードパーティとの戦い編
- バージョン番号は、A.B または A.B.C の形式で表されます。
- Django のリリースプロセス を参照
- どのDjangoのバージョンに更新するか決めましょう: LTS(Long Term Support) or 最新
- 一足飛びにバージョンアップも可能ですが、各機能リリースを段階的に実施する方が対応する差分が小さくなります。
$ python -Wa manage.py check
で既存の警告を対応しましょう。この時サードパーティパッケージも合わせて対応する必要があるかもしれません。- リリースノートやDjango Deprecation Timelineにて変更や廃止があった機能がある場合はそちらも対応します。
- 既存の警告の対応をしたら、新しいバージョンのDjangoをインストールしましょう。
$ pip install -U Django
- アップデートが完了したらテストを実行しましょう。この際にも
-Wa
コマンドラインオプションかPYTHONWARNINGS=always
環境変数を使って警告を表示するとよいでしょう。
django-upgrade の活用
- Pythonコードはdjango-upgrade で自動で書き換えが可能です。
- 新しい記述方法があった場合、非推奨でなくても書き換えられることがあるので取捨選択しましょう。
- Pythonファイルが対象となるので、Django Templateやフロントエンドのコードに影響がないかは別途確認しましょう。
- 移行対象であるDjangoが使用できるPythonやDBのバージョンを確認しておきましょう。
- 2023年12月でLTSであるDjango4.2の場合、以下のバージョンをサポートしています。
- Python 3.8〜3.12(Django 4.2.8から)
- MySQL 8.0以上
- PostgreSQL 12以上
- MariaDB 10.4以上
- サポートしているバージョンに満たない場合、以下の選択肢が考えられます。
- 先んじてバージョンアップを済ませておく: 影響範囲を絞れる。リリースが複数回なのを許容できるならおすすめ。
- リリース時に同時にバージョンアップする: リリースは一度で済むが、影響範囲が大きくなるので計画は慎重に。
- 各バージョンごとの対応
- Pythonは3系であれば基本的に動作します。しかしバージョンを重ねるうちに非推奨になり、削除されるものもあるので、What's New in Pythonを読んで影響範囲は確認しておくとよいでしょう。
- MySQLは5.7以前から8.0に移行する場合は、DBだけでなくアプリケーションの変更も必要な場合があるので要検証。
- PostgreSQL 12に上げれるなら、拡張機能の制約がない限り15まで上げられるはずので検討しましょう。
- 一度アップデートしてもそれで終わりではありません。不具合やセキュリティパッチがあったときに来づける仕組みを作りましょう。
- dependabotやRenovateを活用して、パッチリリースがあったときに自動でPR(Pull Request)を作ってくれる仕組みを導入しましょう。
- バグフィックスやセキュリティ対応のPRが作成されたときに、CI/CD環境を整備して自動テストが実行されると影響範囲が確認しやすくなります。
- これまでDjangoに絞って説明してきましたが、実際には他のサードパーティパッケージも使用していることがあるのでそちらの観点も加えて記載します。
- 影響範囲に応じて必要最小限に留めるか、なるべくすべてのパッケージをバージョンアップするか検討して進ましょう。
- 既存のローカル開発環境の内容を確認しましょう。requirements.txtやpyproject.tomlにPythonの依存関係が記述していることが期待されます。
- 本番環境に近づけた環境を準備しましょう。コンテナで動作している場合、
docker compose
のような環境を活用できます。 - OSによってインストールできなかったり、DBやミドルウェアがインストールしていないと
pip install
できない場合もあるので環境の準備は重要です。- WSGIサーバー(macOS/Linuxのみ): gunicorn
- MySQL: mysqlclient
- PostgreSQL: psycopg, psycopg2
- Mecab: mecab-python3
-
Djangoに依存するパッケージだけをアップデートすることで、バージョンアップ時の影響範囲を最小化できます。
-
pipdeptree のようなツールを使うことで、Djangoに依存しているパッケージを一覧で表示できるので活用しましょう。
# Djangoに依存したパッケージ一覧を表示 $ pipdeptree --reverse --packages django Django==4.2.10 ├── django-anymail==10.2 [requires: Django>=2.0] ├── django-appconf==1.0.6 [requires: Django] │ └── django-compressor==4.4 [requires: django-appconf>=1.0.3] ├── django-debug-toolbar==4.3.0 [requires: Django>=3.2.4] ├── django-ical==1.9.2 [requires: Django>=3.2] ├── django-otp==1.3.0 [requires: Django>=3.2] ├── django-recurrence==1.11.1 [requires: Django>=2.2] │ └── django-ical==1.9.2 [requires: django-recurrence>=1.11.1] ├── django-silk==5.1.0 [requires: Django>=3.2] └── django-storages==1.14.2 [requires: Django>=3.2]
-
それ以外にもDjangoが要求するパッケージのバージョンが更新されていることもあるので、必要に合わせて更新してください。
- プロジェクトでrequirements.txtを用意している場合は、新しくvenv環境を作った後にバージョン情報を指定せず一括でアップデートしましょう。
$ pip install -r requirements.txt -c constraints.txt
のようにバージョンを固定している場合、$ pip install -Ur requirements.txt
とすれば依存パッケージの記述を変更することなく実行できます。- TODO: requirements.txtやpyproject.tomlにパッケージのバージョン情報も含めて記述している場合
- Djangoの場合と同様にパッケージのドキュメントやリリースノートを確認し、アプリケーションへの影響を確認しながら更新しましょう。
- メジャーバージョンアップが行われていた場合、アプリケーションへの変更も大きいと考えられるのでどこまで対応が必要かは精査が必要です。
- アプリケーションの影響が無視できない場合は、影響が少ないできるだけ最新のバージョンにすることも検討してください。
- ex) 現在1.x系のバージョンを使っているが、2.x系での変更が大きいので1.x系の最新バージョンに更新しておく。
- 最新のバージョンでなく、特定のバージョンを選択した理由などは課題管理システムに記録を残しておくと、次回対応時に役立ちます。
- ex) OpenSearchのように使用しているミドルウェアで使えるバージョンが固定されている。
- そのまま使える場合はテストを通して動作を確認してOKと判断もできますが、 動作しない場合は検討が必要 です。
- 選択肢としては以下の4つが考えられます。
- 作者にPRを送って変更を取り込んでもらう: 代替パッケージがない場合はこれが理想です。他にも同じように困っている人の助けにもなります。
- ForkやPatchを当てて自分たちでメンテナンスする: 1が叶わないこともあります。その場合は必要な変更をして使う形になります。ただし本家の更新が再開されたときは差分を吸収するのが大変です。
- 別なパッケージに置き換える: 本家の更新は止まっていても、別のパッケージで新しく再出発していたりするケースもあります。その場合はこちらになりますが、アプリケーションの変更が小さいとは限りません。
- 自分たちで自作する: 最終手段のように見えますが、Djangoの更新により本体に搭載されている場合もあります。大小ありますがアプリケーションの変更も必要になるでしょう。