Djangoで迅速な開発を行うための構造とCI/CD [ 3.x対応 ]
私はPythonを書き始めて8年程経っていまして、利用用途としてはWeb系の開発が多く、特にLinuxが好きなこともあり、小さいシステム、再利用性を設計の優先事項としていた自分にとって、Djangoはうってつけのフレームワークだったので現在もほとんどのWebシステムはDjangoで開発することが多いです。
Djangoはモジュール化を推進しており、作れば作るほど、将来、反復して開発する作業が無くなるので、使い込むほど開発効率が良くなり、特に受託開発では重宝すると思います。
Djangoのプロジェクトを開始するときは長年使ってきて、最終形みたいな構造がありまして、コード内に直接注釈を追加して説明します。
.
├── .idea # メモ類
├── .trash # 開発中のメールファイル、ログなど
├── .vscode # vscodeの設定
├── .dockerignore # Dockerにマウントしないファイル、ディレクトリの設定
├── .env # pipenvで読み込む環境変数
├── .gcloudignore # GCP Container Registryにマウントしないファイル、ディレクトリの設定
├── .gitignore # バージョン管理に含めないファイル、ディレクトリの設定
├── .git # バージョン管理
├── Dockerfile # 最新のDebian系イメージをベースにしたWeb向けのPythonイメージ
├── Pipfile # Pythonライブラリの依存管理
├── Pipfile.lock
├── README.md
├── cloudbuild.yaml # GCP、CloudBuildで実行するCI/CDの設定
├── docker-compose.yaml # Djangoアプリケーション以外の依存しているミドルウェア e.g. PostgreSQL, Redis, 他マイクロサービスなど
├── iam.json # GCPで発行している開発環境中に使うサービスアカウント
├── manage.py
├── pytest.ini # Pytestの設定
├── requirements.txt
└── src # プロジェクトソース
├── __init__.py
├── app # モジュール、過去に作ったモジュールをこの単位で追加している e.g. app, payment, blog
│ ├── __init__.py
│ ├── admin.py # 自動生成して実装 ※後述
│ ├── cfg.py # AppConfig Class
│ ├── decorators.py # デコレーター
│ ├── forms.py # フォーム
│ ├── locale # モジュールの翻訳セット
│ │ ├── en
│ │ │ └── LC_MESSAGES
│ │ │ ├── django.mo
│ │ │ └── django.po
│ │ └── ja
│ │ └── LC_MESSAGES
│ │ ├── django.mo
│ │ └── django.po
│ ├── migrations # スキーマのマイグレーション
│ │ ├── 0001_initial.py
│ │ └── __init__.py
│ ├── models.py # モデル
│ ├── signals.py # モデルのアクションから実行させたいフック処理やサブプロセスで実行した処理
│ ├── static # モジュールの静的ファイルはGCSを使う
│ │ ├── css
│ │ │ ├── uikit-core-rtl.css
│ │ │ ├── uikit-core-rtl.min.css
│ │ │ ├── uikit-core.css
│ │ │ ├── uikit-core.min.css
│ │ │ ├── uikit-rtl.css
│ │ │ ├── uikit-rtl.min.css
│ │ │ ├── uikit.css
│ │ │ └── uikit.min.css
│ │ ├── img
│ │ │ └── photo.jpg
│ │ ├── js
│ │ │ ├── components
│ │ │ │ ├── countdown.js
│ │ │ │ ├── countdown.min.js
│ │ │ │ ├── filter.js
│ │ │ │ ├── filter.min.js
│ │ │ │ ├── lightbox-panel.js
│ │ │ │ ├── lightbox-panel.min.js
│ │ │ │ ├── lightbox.js
│ │ │ │ ├── lightbox.min.js
│ │ │ │ ├── notification.js
│ │ │ │ ├── notification.min.js
│ │ │ │ ├── parallax.js
│ │ │ │ ├── parallax.min.js
│ │ │ │ ├── slider-parallax.js
│ │ │ │ ├── slider-parallax.min.js
│ │ │ │ ├── slider.js
│ │ │ │ ├── slider.min.js
│ │ │ │ ├── slideshow-parallax.js
│ │ │ │ ├── slideshow-parallax.min.js
│ │ │ │ ├── slideshow.js
│ │ │ │ ├── slideshow.min.js
│ │ │ │ ├── sortable.js
│ │ │ │ ├── sortable.min.js
│ │ │ │ ├── tooltip.js
│ │ │ │ ├── tooltip.min.js
│ │ │ │ ├── upload.js
│ │ │ │ └── upload.min.js
│ │ │ ├── uikit-core.js
│ │ │ ├── uikit-core.min.js
│ │ │ ├── uikit-icons.js
│ │ │ ├── uikit-icons.min.js
│ │ │ ├── uikit.js
│ │ │ └── uikit.min.js
│ │ ├── manifest.json
│ │ ├── package.json
│ │ └── yarn.lock
│ ├── templates # モジュールのテンプレート
│ │ ├── _base.html
│ │ ├── _footer.html
│ │ ├── _global_menu.html
│ │ ├── _input_alert.html
│ │ ├── dashboard.html
│ │ ├── free-content.html
│ │ ├── index.html
│ │ ├── login.html
│ │ ├── logout.html
│ │ ├── paid-content.html
│ │ └── registration.html
│ ├── templatetags # モジュールのカスタムテンプレートタグ
│ │ ├── __init__.py
│ │ └── customtag.py
│ ├── tests.py # モジュールのテスト
│ ├── urls.py # モジュールのルーティング
│ └── views.py # モジュールのコントローラー
├── asgi.py # asgi
├── settings.py # プロジェクトの設定
├── urls.py # プロジェクトのルーティング
└── wsgi.py # wsgi
デザインリソースはヒアリングに応じてフレームワークを変えています。特に指定がなければUIKITを使うことが多いです。
プロジェクトを始める
この記事はDjangoをGCPにデプロイする前提で開発する場合の実践的な内容になっています。GCPを使うことを前提としておりますので、まずはGCPにプロジェクトを作成し、必要な前提条件を満たしましょう。アカウント作成、支払情報設定の説明は省略します。
IAMでGoogle Cloud Storage(GCS)へローカルから接続するためのサービスアカウントを作る
GCPの「IAMと管理」からサービスアカウントを選択して、役割に適当な名前をつけてサービスアカウントを作成しましょう。作成したアカウントがリストに表示されるので、メニューを押して鍵を作成でJSONを選択します。続いて、左メニューから「IAM」を選択して、アカウントリストからさきほど作成したアカウントの編集ボタンを押し、役割を「ストレージの管理者」に設定すれば、ダウンロードしたサービスアカウントファイルにGCSへの権限が付与されているます。後ほどプロジェクト内で使うので、ここでは便宜上「iam.json」で保存しておいてください。
GCP製品を利用するためのAPIを有効化する
GCPメニューから必要な製品を選択すると、APIが有効でない場合は「有効にする」と表示されるので、必要なAPIの製品のリンクを押して、有効化しましょう。
CloudBuildでコンテナイメージの作成、CloudRunへデプロイできるように権限を付与する
さきほど開いた「IAMと管理」の画面にCloudBuildに割当てられたサービスアカウントがあるので、権限を追加しましょう。
「CloudRun管理者」「CoudRunサービスエージェント」「ストレージ管理者」「AppEngine管理者」「プロジェクト編集者」を付与して保存しましょう。
Djangoのプロジェクトを作成する
準備お疲れさまでした🤯
これでGCPへデプロイする準備が整ったので、GCP向けのDjangoプロジェクトを作成しましょう。まずはプロジェクトのディレクトリを作成して、pipenvで環境を構築します。この記事は複数回に渡って、ハンズオン形式で進めるため、Gitにコードを用意していますので、以下からクローンしてください。
コードの内容については複数回に渡って、実践で効率よく開発するためのノウハウと、無駄のない実装方法について解説します。興味がありましたら読んで頂けると嬉しいです。
※このプロジェクトはGCPのストレージと以下のライブラリに依存しています。
# Pipfile
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[scripts]
[dev-packages]
flake8 = "*"
ipython = "*"
pytest = "*"
pytest-django = "*"
autopep8 = "*"
factory_boy = "*"
[packages]
django-storages = {extras = ["google"],version = "*"}
pytz = "*"
Django = "*"
django-extensions = "*"
uwsgi = "*"
psycopg2-binary = "*"
bcrypt = "*"
uvicorn = "*"
google-auth = "*"
django-widget-tweaks = "*"
[requires]
python_version = "3.7"
Djangoの説明は端折って、CloudBuildによるCI/CDとCloudRunへのデプロイについて知りたい方は以下の記事を参考にしてください。