Djangoの拡張性と保守性を実現するディレクトリ構成&実装ガイド

thumbnail-django-directory-structure-guide Django

DjangoでWebサイトを構築する際に、毎回フォルダ構成を悩むので、個人的なベストプラクティスを考えてみました。

改善点や修正点があれば、その都度追記していきます。

0. 前提条件

フレームワークはDjangoのみ使用します。

フロントエンドフレームワークは使用しない前提です。
HTML、CSS、JSのみ使用します。

1. プロジェクト全体のディレクトリ構成

最初にプロジェクト全体のディレクトリ構成を記載します。

myproject/
├── Dockerfile
├── docker-compose.yml
├── manage.py
├── myproject/
│   ├── __init__.py
│   ├── settings/
│   │   ├── __init__.py       # base, development, productionの設定を読み込むためのファイル
│   │   ├── base.py           # 全環境共通の設定
│   │   ├── development.py    # 開発環境専用の設定(例: DEBUG=True)
│   │   └── production.py     # 本番環境専用の設定(例: DEBUG=False, セキュリティ強化)
│   ├── urls.py               # プロジェクト全体のURL設定
│   ├── asgi.py
│   └── wsgi.py
├── apps/
│   ├── app1/                 # 各ドメインごとのアプリケーション
│   │   ├── __init__.py
│   │   ├── models/
│   │   │   ├── __init__.py   # models/user.py, product.py, order.py等を統合
│   │   │   ├── user.py       # ユーザー関連のモデル
│   │   │   ├── product.py    # 商品関連のモデル
│   │   │   └── order.py      # 注文関連のモデル
│   │   ├── admin/
│   │   │   ├── __init__.py   # 各admin設定を統合
│   │   │   ├── user.py       # ユーザー関連のadmin登録
│   │   │   ├── product.py    # 商品関連のadmin登録
│   │   │   └── order.py      # 注文関連のadmin登録
│   │   ├── views/
│   │   │   ├── __init__.py   # 必要に応じて各ビューを統合
│   │   │   ├── user_views.py     # ユーザー関連のビュー
│   │   │   ├── product_views.py  # 商品関連のビュー
│   │   │   └── order_views.py    # 注文関連のビュー
│   │   ├── urls.py           # app1内のURL設定
│   │   └── tests/
│   │       ├── __init__.py
│   │       ├── test_models.py    # モデルのテスト
│   │       ├── test_views.py     # ビューのテスト
│   │       └── test_forms.py     # フォームなどその他のテスト
│   └── core/                 # サイト全体で再利用する汎用的な機能をまとめたアプリ
│       ├── __init__.py
│       ├── models.py         # 共通モデル(必要な場合)
│       ├── views.py          # 全体共通のビュー(例: ランディングページ、エラーページ)
│       ├── urls.py           # 共通ビュー用のURL設定
│       ├── templatetags/     # カスタムテンプレートタグ
│       └── context_processors.py  # 共通のコンテキストプロセッサ
├── templates/
│   ├── base.html             # 共通レイアウト:<head>、header, menu, footerを含む
│   ├── includes/
│   │   ├── header.html       # 表示部分のヘッダー(サイトタイトル、ロゴなど)
│   │   ├── menu.html         # ナビゲーションメニュー(各ページへのリンク)
│   │   └── footer.html       # フッター(コピーライト等)
│   └── app1/
│       └── index.html        # app1固有のページテンプレート(base.htmlを継承)
└── static/
    ├── css/
    │   └── style.css         # 共通のスタイルシート
    └── js/
        ├── common.js         # 全ページで利用する共通のJavaScriptコード
        ├── app1/             # アプリ・ページ固有のJS
        │   ├── index.js      # app1のトップページ専用のJS
        │   └── about.js      # app1のAboutページ専用のJS
        └── app2/
            ├── dashboard.js  # app2のダッシュボード専用のJS
            └── report.js     # app2のレポート専用のJS

2. 各主要ファイルの説明・実装例

2.1. settings

base.pyを全環境共通の設定ファイルとし、開発環境と本番環境で別ファイルを用意します。

├── myproject/
│   ├── __init__.py
│   ├── settings/
│   │   ├── __init__.py       # base, development, productionの設定を読み込むためのファイル
│   │   ├── base.py           # 全環境共通の設定
│   │   ├── development.py    # 開発環境専用の設定(例: DEBUG=True)
│   │   └── production.py     # 本番環境専用の設定(例: DEBUG=False, セキュリティ強化)
│   ├── urls.py               # プロジェクト全体のURL設定

ローカル、ステージング、本番の3環境でファイルを用意してもいいと思います。

development.pyとproduction.pyでは、以下のように書くことで、base.pyを読み込みます。

# myproject/settings/development.py

from .base import *

DEBUG = True
ALLOWED_HOSTS = ['localhost', '127.0.0.1']

# 開発環境専用の追加設定(例: メールバックエンド、キャッシュ設定等)
# myproject/settings/production.py

from .base import *

DEBUG = False
ALLOWED_HOSTS = ['yourdomain.com']

# 本番環境専用の追加設定(例: セキュリティ強化、ログ設定など)

2.2. アプリケーション内ファイル例

モデルについては、models.pyにまとめて書くのではなく、テーブルごとにファイルを分けます。

├── apps/
│   ├── app1/                 # 各ドメインごとのアプリケーション
│   │   ├── __init__.py
│   │   ├── models/
│   │   │   ├── __init__.py   # models/user.py, product.py, order.py等を統合
│   │   │   ├── user.py       # ユーザー関連のモデル
│   │   │   ├── product.py    # 商品関連のモデル
│   │   │   └── order.py      # 注文関連のモデル

__init__.pyには必要なモデルをまとめてインポートし、外部からapp1.modelsのような形でアクセスできるようにします。

from .user import *
from .product import *
from .order import *

admin.pyについても、modelsディレクトリに対応するため、adminディレクトリを作成し、その中に各モデルに対応するadmin設定ファイルを配置します。

│   │   ├── admin/
│   │   │   ├── __init__.py   # 各admin設定を統合
│   │   │   ├── user.py       # ユーザー関連のadmin登録
│   │   │   ├── product.py    # 商品関連のadmin登録
│   │   │   └── order.py      # 注文関連のadmin登録

views.pyもそのまま使用せず、viewsというサブディレクトリを作成し、機能ごとにファイルを分割します。

│   │   ├── views/
│   │   │   ├── __init__.py   # 必要に応じて各ビューを統合
│   │   │   ├── user_views.py     # ユーザー関連のビュー
│   │   │   ├── product_views.py  # 商品関連のビュー
│   │   │   └── order_views.py    # 注文関連のビュー

そして、coreというサイト全体で再利用する汎用的な機能をまとめたアプリを作成します。

│   └── core/                 # サイト全体で再利用する汎用的な機能をまとめたアプリ
│       ├── __init__.py
│       ├── models.py         # 共通モデル(必要な場合)
│       ├── views.py          # 全体共通のビュー(例: ランディングページ、エラーページ)
│       ├── urls.py           # 共通ビュー用のURL設定
│       ├── templatetags/     # カスタムテンプレートタグ
│       └── context_processors.py  # 共通のコンテキストプロセッサ

coreアプリ内も状況に応じて、modelsやviewのディレクトリを作成してもいいと思います。

2.3. templates

templatesについては以下のような構成です。

├── templates/
│   ├── base.html             # 共通レイアウト:<head>、header, menu, footerを含む
│   ├── includes/
│   │   ├── header.html       # 表示部分のヘッダー(サイトタイトル、ロゴなど)
│   │   ├── menu.html         # ナビゲーションメニュー(各ページへのリンク)
│   │   └── footer.html       # フッター(コピーライト等)
│   └── app1/
│       └── index.html        # app1固有のページテンプレート(base.htmlを継承)

Webアプリケーションは基本的にページの構成が同じような形になるため、共通部分としてbase.htmlを用意します。

base.html

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}My Website{% endblock %}</title>
    <link rel="stylesheet" href="{% static 'css/style.css' %}">
    {% block head_extra %}
    <!-- 各ページで追加するhead内要素 -->
    {% endblock %}
</head>
<body>
    {% include "includes/header.html" %}
    {% include "includes/menu.html" %}

    <div class="content">
        {% block content %}
        <!-- 各ページ固有のコンテンツ -->
        {% endblock %}
    </div>

    {% include "includes/footer.html" %}
    <script src="{% static 'js/common.js' %}"></script>
    {% block extra_js %}
    <!-- 各ページ固有のJSを追加 -->
    {% endblock %}
</body>
</html>

ヘッダー、フッター、メニューについても同じようテンプレートを作成します。

includes/header.html

<header>
    <h1>My Website</h1>
</header>

includes/menu.html

<nav>
    <ul>
        <li><a href="{% url 'app1:index' %}">ホーム</a></li>
        <li><a href="{% url 'app1:about' %}">About</a></li>
        <li><a href="{% url 'app1:contact' %}">Contact</a></li>
    </ul>
</nav>

includes/footer.html

<footer>
    <p>© 2025 My Website. All rights reserved.</p>
</footer>

各ページでは、base.htmlを{% extends %}を使って継承し、固有のコンテンツ部分(block contentなど)を上書きして記述します。

app1/index.html

{% extends "base.html" %}

{% block title %}ホーム - My Website{% endblock %}

{% block content %}
<h2>Welcome to My Website</h2>
<p>ここにホームページの固有コンテンツを記述します。</p>
{% endblock %}

{% block extra_js %}
<script src="{% static 'js/app1/index.js' %}"></script>
{% endblock %}

2.4. 静的ファイルの実装例

jsファイルは、共通部分とアプリケーションのページごとで分けてファイルを作成します。

└── static/
    ├── css/
    │   └── style.css         # 共通のスタイルシート
    └── js/
        ├── common.js         # 全ページで利用する共通のJavaScriptコード
        ├── app1/             # アプリ・ページ固有のJS
        │   ├── index.js      # app1のトップページ専用のJS
        │   └── about.js      # app1のAboutページ専用のJS
        └── app2/
            ├── dashboard.js  # app2のダッシュボード専用のJS
            └── report.js     # app2のレポート専用のJS

3. その他

Dockerについては

myproject/
├── Dockerfile
├── docker-compose.yml
├── manage.py
├── myproject/
└── apps/

でいいと思いますが、環境ごとに複数のDockerファイルが必要な場合は

myproject/
├── docker/
│   ├── Dockerfile
│   ├── docker-compose.dev.yml
│   └── docker-compose.prod.yml
├── manage.py
├── myproject/
└── apps/

のようにdockerディレクトリを作成してもいいと思います。

その他、改善等が発生次第、追記してきます。

コメント

タイトルとURLをコピーしました