Python | Web フレームワーク:Django の分割構造

Python
スポンサーリンク

概要(Django の分割構造=「大きな家を部屋ごとに区切る設計」)

Django の「分割構造」は、
一言でいうと「プロジェクト全体を、役割ごと・機能ごとにきれいに分ける仕組み」です。

一番大きな単位が「プロジェクト」、
その中に「アプリ」がいくつも入るイメージです。

プロジェクト=“サイト全体”
アプリ=“サイトの中の機能のまとまり(ブログ機能、会員機能、ショップ機能など)”

さらにアプリの中も、
モデル、ビュー、URL、テンプレート、静的ファイル…と役割ごとに分かれます。

この「分割構造」をちゃんと理解しておくと、
コードが増えても迷子になりにくくなり、
後から機能を追加したり、別プロジェクトに移植したりするのが一気に楽になります。

プロジェクトとアプリの関係をイメージする

プロジェクト=“サイト全体の土台”

django-admin startproject config のようにして作るのが「プロジェクト」です。
例えば、こんな構造になります。

mysite/
  manage.py
  config/
    __init__.py
    settings.py
    urls.py
    asgi.py
    wsgi.py

ここで大事なのは、
settings.py と urls.py が「プロジェクト全体の中枢」だということです。

settings.py は「このサイトはどんなルールで動くか」を決める場所。
urls.py は「このサイトの入り口(URL)をどう振り分けるか」を決める場所。

プロジェクトは「全体の設定と入り口」を持ち、
実際の機能はアプリに任せる、という役割分担になっています。

アプリ=“機能ごとの部屋”

python manage.py startapp blog のようにして作るのが「アプリ」です。
例えば blog アプリはこんな構造になります。

blog/
  __init__.py
  admin.py
  apps.py
  models.py
  views.py
  urls.py(自分で作る)
  templates/(自分で作る)
  static/(自分で作る)
  migrations/

アプリは「一つの機能のまとまり」です。
ブログ機能なら blog アプリ、
会員管理なら accounts アプリ、
EC 機能なら shop アプリ、
というように分けていきます。

一つのプロジェクトの中に、
複数のアプリが共存するのが Django の基本スタイルです。

アプリの中の分割(models / views / urls / templates / static)

models.py=「データベースの設計図」

models.py には、そのアプリで扱うデータ構造を書きます。
ブログなら Post、Comment、カテゴリなどのモデルがここに並びます。

# blog/models.py
from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=200)
    body = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.title
Python

この 1 クラスが DB の 1 テーブルに対応し、
Django ORM を通してデータを読み書きできるようになります。

「データの形とルール」は models.py に集約する、
というのが大事な考え方です。

views.py=「リクエストを受けてレスポンスを返す人」

views.py には、「URL ごとに何をするか」の処理を書きます。

# blog/views.py
from django.shortcuts import render, get_object_or_404
from .models import Post

def post_list(request):
    posts = Post.objects.order_by("-created_at")
    return render(request, "blog/post_list.html", {"posts": posts})

def post_detail(request, pk):
    post = get_object_or_404(Post, pk=pk)
    return render(request, "blog/post_detail.html", {"post": post})
Python

ビューは、
リクエストを受け取る
必要なデータをモデルから取り出す
テンプレートに渡して HTML を作る
という「流れの司令塔」です。

「画面ごとの処理」は views.py に集約する、
というイメージを持っておくと整理しやすくなります。

urls.py(アプリ側)=「そのアプリの入り口の一覧」

blog アプリの中にも urls.py を作り、
そのアプリに関係する URL をまとめます。

# blog/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path("", views.post_list, name="post_list"),
    path("<int:pk>/", views.post_detail, name="post_detail"),
]
Python

これで、
/blog/ → post_list
/blog/1/ → post_detail(pk=1)
という対応になります。

プロジェクト側の urls.py では、
この blog.urls を「/blog/ 以下に割り当てる」形で include します。

# config/urls.py
from django.urls import path, include

urlpatterns = [
    path("blog/", include("blog.urls")),
]
Python

こうすることで、
「プロジェクトは大きな入口だけ」「アプリは自分の担当部分だけ」
を書く構造になります。

templates/=「画面の見た目(HTML)の置き場」

テンプレートは、
HTML の中に Django テンプレートタグ({{ }}{% %})を書いて、
ビューから渡されたデータを埋め込むためのファイルです。

アプリごとにテンプレートを分けるのが定番で、
例えば blog アプリならこうします。

blog/
  templates/
    blog/
      post_list.html
      post_detail.html

post_list.html の例はこんな感じです。

<!-- blog/templates/blog/post_list.html -->
<h1>ブログ一覧</h1>

{% for post in posts %}
  <h2><a href="{% url 'post_detail' pk=post.pk %}">{{ post.title }}</a></h2>
  <p>{{ post.created_at }}</p>
{% endfor %}

「見た目」はテンプレートに閉じ込め、
ビューは「どのテンプレートに何を渡すか」だけを考える、
という分業がポイントです。

static/=「CSS・JS・画像などの静的ファイル」

アプリごとに static フォルダを作り、
その中に CSS や JS、画像などを置きます。

blog/
  static/
    blog/
      style.css

テンプレートからは、
{% load static %} を使って参照します。

{% load static %}
<link rel="stylesheet" href="{% static 'blog/style.css' %}">

これで、
「見た目のロジック(HTML)」と「装飾(CSS)」も分離されます。

それぞれがどうつながるかを一気に眺める

リクエストが来てからレスポンスが返るまで

ブログの一覧ページ /blog/ にアクセスされたとき、
裏側ではこんな流れになっています。

ブラウザが /blog/ にリクエストを送る。
プロジェクトの config/urls.py/blog/blog.urls に振り分ける。
blog/urls.pypath("", post_list, ...) がマッチし、post_list ビューが呼ばれる。
post_list ビューが Post.objects.order_by(...) でモデルからデータを取り出す。
ビューが render(request, "blog/post_list.html", {"posts": posts}) を呼ぶ。
テンプレート blog/post_list.htmlposts を使って HTML を生成する。
生成された HTML がレスポンスとしてブラウザに返る。

この一連の流れの中で、
プロジェクト、アプリ、models、views、urls、templates が
それぞれの役割を果たしています。

「どこで何をしているか」が分かると、
バグが出たときに「どこを見ればいいか」も分かるようになります。

アプリを増やしても構造が崩れない理由

例えば、同じプロジェクトに shop アプリを追加したとします。

shop アプリにも models.py, views.py, urls.py, templates/, static/ ができます。
プロジェクト側の urls.py に path("shop/", include("shop.urls")) を足せば、
/shop/ 以下は shop アプリの担当になります。

blog と shop は、
お互いの中身を知らなくても動きます。
共通しているのは「Django の約束(分割構造)」だけです。

この「アプリごとに完結していて、プロジェクトがそれらを束ねる」構造が、
Django の分割構造の一番おいしいところです。

設計のときに意識してほしいポイント

「機能ごとにアプリを分ける」感覚を持つ

最初は、
全部を一つのアプリに詰め込みたくなるかもしれません。

でも、
ブログ機能
会員機能
問い合わせフォーム
EC 機能

など、明らかに役割が違うものは、
アプリを分けた方が長期的に楽です。

アプリを分けると、
そのアプリだけを別プロジェクトに持っていくこともできますし、
テストやリファクタリングの単位としても扱いやすくなります。

「1 ファイルに詰め込みすぎない」

views.py に 100 個のビュー関数が並び始めたら、
さすがに読みにくくなります。

そういうときは、
views ディレクトリを作ってファイルを分割したり、
クラスベースビューで整理したりする、
という次のステップに進めばいいです。

大事なのは、
「役割ごとに分ける」という感覚を常に持っておくこと。

モデルは models.py(または models/ 配下)
ビューは views.py(または views/ 配下)
URL は urls.py
テンプレートは templates/

という「分割の軸」を崩さない限り、
細かい分け方は後からいくらでも調整できます。

まとめ(Django の分割構造は「迷子にならないための地図」)

Django の分割構造を初心者目線でまとめると、こうなります。

プロジェクトは「サイト全体の土台とルール(settings, 入口の urls)」を持ち、アプリは「機能ごとのまとまり(blog, accounts, shop など)」としてその中にぶら下がる。
アプリの中は、models(データ)、views(処理)、urls(入り口)、templates(見た目)、static(CSS/JS/画像)と役割ごとに分かれていて、「どの種類のコードをどこに置くか」が明確になっている。
リクエストは「プロジェクトの urls → アプリの urls → ビュー → モデル → テンプレート」という流れで処理され、この流れを一度頭に描けるようになると、Django のコード全体が一気に読みやすくなる。

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