この記事はDjango配下の設計・実装の入口です。Modelはデータ、Viewはリクエストに対する処理とresponse、Templateは表示を受け持ちます。URL設定はどのViewを呼ぶかをframeworkへ伝えます。MVT/MTVという文字順だけで処理順を覚えないでください。
調べたい役割から子ページを選ぶ
次の子ページから対象を選択してください。一般MVCの他製品比較は後半に残していますが、Djangoの実装を調べる場合は先にこちらを使います。
- ビュー(View):リクエスト処理とresponse
- テンプレート(Template):表示の記述
- モデル(Model):データの定義と操作
- ルーティングの作成:URLとViewの対応
- viewからtemplateへの遷移方法:contextと描画
名前の置換ではなく処理の担当を見る
Django 5.2公式FAQは、Viewを「どのデータを見せるか」、Templateを「どう見せるか」と整理し、Controllerに当たるものをURL設定に従ってViewへ振り分けるframework自体と説明します。「ViewとControllerが逆転」と一対一で暗記するとURLconfの仕事が抜けます。
すべてのViewがDBやTemplateを使うわけではありません。HttpResponseやJSONを直接返すことも、アクセスを拒否することもあります。責務分離は認証/認可・入力検証・transaction・例外処理を自動で満たす保証ではなく、必要な境界を設計して検査します。
1件表示の小さな実例
Python3.12.10/Django5.2.18で専用の空設定と一時メモリDBを使って確認する例です。既存projectにsettingsを上書きしたりDB作成を実行する手順ではありません。以下は別々の4ファイルです。新しい検証用projectで、このappをINSTALLED_APPSに登録し、DjangoTemplatesのAPP_DIRS=Trueを設定し、projectのURLconfからこのappのurlsをincludeする構成を前提にします。
catalog/models.py:教材用の公開商品名だけを持つ独自モデルです。標準auth.Userのname/emailを仮定せず、顧客/秘密情報を表示しません。
from django.db import models
class CatalogItem(models.Model):
name = models.CharField(max_length=100)
catalog/views.py:存在しないpkは404、存在すれば辞書contextでTemplateへ渡します。公開カタログを読むだけの例で、個人別データの認可や書込みAPIは含みません。
from django.shortcuts import get_object_or_404, render
from .models import CatalogItem
def detail(request, pk):
item = get_object_or_404(CatalogItem, pk=pk)
return render(request, "catalog/detail.html", {"item": item})
catalog/urls.py:整数converterで一致した値をViewのpk引数へ渡します。ルートURLではなく、include先のprefixとの組合せで実URLが決まります。
from django.urls import path
from . import views
app_name = "catalog"
urlpatterns = [path("items/<int:pk>/", views.detail, name="detail")]
catalog/templates/catalog/detail.html:app名のdirectoryで名前を分けます。通常のautoescapeを保ち、safeで入力をそのままHTML化しません。
<!doctype html>
<html lang="ja">
<meta charset="utf-8">
<title>公開カタログ</title>
<h1>{{ item.name }}</h1>
</html>
この例のfixtureではproject側でpath("catalog/", include("catalog.urls"))を登録し、/catalog/items/1/が表示URLになります。reverseはcatalog:detailへpkを渡します。実projectのschema作成はその環境の承認済み手順に従い、CWiki本番でmigrateする指示ではありません。
表示されない時は境界を順に確認する
- URLが一致しない:project側のinclude prefix、末尾slash、converterと引数名を確認します。数値でないpathはこの例ではViewまで届きません。
- 404になる:route不一致と、Viewが対象行を見つけられない場合を分けます。pkは権限の証明ではなく、非公開データでは認可済みQuerySet等を別に用意します。
- TemplateDoesNotExist:template名、配置、APP_DIRS/DIRS、app登録を確認。base.htmlをextendsするならその存在とblock名も必要です。
- 表示が空:contextのキーと属性を確認します。通常のDjangoTemplateで未定義変数が空文字になる場合もあり、「エラーがないから正しい」と判断しません。
- モデル定義とDBが違う:Modelのコード、実schema、利用DBを区別します。動作確認のために実DBを初期化したり権限を広げたりしません。
fixtureではroute/reverse、正常表示、存在しない行、非整数path、template探索とescape等を確認します。実ブラウザ、実projectの認証/認可、他製品の比較コードの実行や本番運用まで検証した意味ではありません。
一次資料:Django 5.2 Tutorial 3、URL dispatcher。利用中の版と照合してください。
| この記事の要点 |
|---|
|
MVC とは
MVC (Model-View-Controller) はアプリケーションの責務を分ける設計パターンです。Web専用ではなく、実装によって役割の境界も異なります。以下はサーバー側HTML生成の説明用の比較です。
| 層 | 役割 | 例 |
|---|---|---|
| Model | データとビジネスロジック | DB 接続、エンティティ、サービスクラス |
| View | 表示(プレゼンテーション) | HTML テンプレート、JSP、Blade、Twig |
| Controller | リクエスト処理と View 選択 | URL ハンドラ、@Controller クラス |
MVC のフロー
- ユーザがブラウザでリクエスト送信
- Controller がリクエストを受信
- Controller が Model を呼び出してデータ取得
- Controller が View にデータを渡す
- View が HTML を生成してレスポンス
主要フレームワーク別の実装
Spring MVC (Java)
比較例の条件:Springの比較用断片です。別ファイルのimports/Repository/設定等を省略しています。示したUserにはemailがないため、次のテンプレートのemail参照をそのまま実行可能と扱いません。SpringのModel引数は画面へ渡す属性用で、JPA Entityそのものとは別です。
// Controller
@Controller
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService; // ← Model 層
@GetMapping("/{id}")
public String show(@PathVariable Long id, Model model) {
User user = userService.findById(id); // Model 呼び出し
model.addAttribute("user", user);
return "users/show"; // ← View 名(Thymeleaf テンプレート)
}
}
// Model (Entity + Service)
@Entity
public class User {
@Id private Long id;
private String name;
}
@Service
public class UserService {
@Autowired private UserRepository userRepository;
public User findById(Long id) {
return userRepository.findById(id).orElseThrow();
}
}
比較例の条件:前のUserのnameのみでemailは未定義です。実モデルの公開可能な属性に合わせてテンプレートを修正します。
<!-- View: resources/templates/users/show.html (Thymeleaf) -->
<h1 th:text="${user.name}">名前</h1>
<p th:text="${user.email}">メール</p>
Laravel (PHP)
比較例の条件:Laravelの別ファイルをまとめた比較例です。namespace/imports/routes/DB構成が必要で、この断片だけでは動きません。fillableは認可の代わりではありません。
// Controller: app/Http/Controllers/UserController.php
class UserController extends Controller {
public function show($id) {
$user = User::findOrFail($id); // Model (Eloquent)
return view("users.show", compact("user")); // View 呼び出し
}
}
// Model: app/Models/User.php
class User extends Model {
protected $fillable = ["name", "email"];
}
比較例の条件:Laravel Blade専用です。Djangoテンプレートと構文を混ぜず、ユーザー情報を見せてよい範囲を別に認可します。
<!-- View: resources/views/users/show.blade.php -->
<h1>{{ $user->name }}</h1>
<p>{{ $user->email }}</p>
Rails (Ruby)
比較例の条件:Railsのcontroller/modelは別ファイルです。DB schema/routes等とname/email属性を仮定した比較例で、実行検証していません。
# Controller: app/controllers/users_controller.rb
class UsersController < ApplicationController
def show
@user = User.find(params[:id]) # Model
# 自動的に app/views/users/show.html.erb をレンダリング
end
end
# Model: app/models/user.rb
class User < ApplicationRecord
end
比較例の条件:Rails ERB専用です。実際のデータ属性と認可を確認します。
<!-- View: app/views/users/show.html.erb -->
<h1><%= @user.name %></h1>
<p><%= @user.email %></p>
MVT とは (Django)
単にViewとControllerの名称が逆転するわけではありません。Django公式FAQではViewは何を提示するか、Templateはどう表示するかを担い、Controllerに当たるのはURL設定から適切なViewへ振り分けるframework自体と説明しています。
| 標準 MVC | Django (MVT) | 説明 |
|---|---|---|
| Model | Model | 同じ |
| View (HTML) | Template | HTML テンプレート |
| Controllerとの比較 | URLconfを使うframeworkの振分けとView | 厳密な一対一対応ではない。Viewは提示データとresponseを決める |
Django (Python) の例
比較例の条件:Django旧比較例です。urls.py/views.py/models.pyは別ファイル、Userは独自モデルで標準auth.Userではありません。Controller相当というコメントは簡略化で、公式FAQのframework側の振分けも含めて読みます。
# urls.py
from django.urls import path
from . import views
urlpatterns = [
path("users/<int:id>/", views.user_detail, name="user_detail"),
]
# views.py (役割は MVC の Controller)
from django.shortcuts import render, get_object_or_404
from .models import User
def user_detail(request, id):
user = get_object_or_404(User, pk=id) # Model 呼び出し
return render(request, "users/detail.html", {"user": user}) # Template
# models.py (Model)
from django.db import models
class User(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField()
比較例の条件:前の旧例はbase.htmlの提供を省略しています。TemplateDoesNotExistやblock名の不一致を確認し、safeによるHTML無条件出力で回避しません。
<!-- templates/users/detail.html (Template) -->
{% extends "base.html" %}
{% block content %}
<h1>{{ user.name }}</h1>
<p>{{ user.email }}</p>
{% endblock %}
MVC のメリット
- 責務分離: 依存を整理すると対象を分けてテストしやすい。ORM/DB等が必要な統合試験もある
- 並行開発: フロント (View) とバック (Controller/Model) を別チームで開発可能
- 保守性: contextのキー/型・URL等の契約を守れば表示変更の影響を限定しやすい。無影響の保証ではない
- 再利用: 同じ Model を複数 View で使い回せる
- テスト容易: Model / Controller を独立して単体テスト可能
MVC の限界とモダンアーキテクチャ
純粋 MVC では Controller がビジネスロジックを抱え込む「Fat Controller」問題が起きがち。モダンな対策:
- Service 層追加: 必要な場合にController/Viewから業務処理を分ける。常に4層へ固定する規則ではない
- Repository 層: DB アクセスを抽象化(Model から分離)
- DTO: Controller ↔ View 間のデータ転送オブジェクト
- Form Request / DTO 検証: バリデーション層の分離
モダンな層構成例 (Spring Boot)
- Controller: HTTP 受付、リクエスト → DTO 変換
- Service: ビジネスロジック、トランザクション境界
- Repository: DB アクセス (JPA / MyBatis)
- Entity: DB マッピング
- DTO: API レスポンス / リクエスト型
SPA + API での MVC
React/Vue + REST API の構成では、JSON APIの表示をフロント側が担う構成もある。SSR/HTMLとの併用等もあり、完全移動が必須ではない:
- サーバ側: Model + Controller (Service 含む)。REST API で JSON 返却
- クライアント側: View (React/Vue コンポーネント) + 状態管理
関連記事
- 環境構築とプロジェクト/アプリの作成
- MVC(MVT)のそれぞれの使い方と説明
- データベースへの接続と操作
- Django Administration
- git管理
- エラー一覧
- バージョンの確認方法
- ログ出力方法
- SQLのログ出力方法
- ログのローテート設定
- settings.pyの定数にアクセスする方法
- 本番環境へのインストールとアプリのデプロイ(apache編)
- 本番環境へのインストールとアプリのデプロイ(nginx編)
- djangoアプリの本番の開始URLを変更する
- 静的(static)ファイルの置き場所と読み込み(画像、css、js )
- CSRFトークンをAjaxで使用する方法
- ajaxの使用例(POST編)
- ファイルのアップロードとファイルの名前
- クイックスタート/チュートリアル
- ログイン機能
- テンプレート側のログイン判定
- ビュー側のログイン判定
- 管理者ユーザーの作成/判定と管理画面
- モデルのjson化とレスポンス
- runserverでポートを指定する方法
- cronによるバッチ実行
- テンプレートで利用する共通のcontextを定義する方法
- プログラムが本番サーバーで反映されない場合の対処法
- APIの作成
- cron用コマンド・ファイルの作成
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript で base URL を取得する方法|window.location.origin
- 4 YouTube Data API v3 エラー一覧|403・400・404 の原因と対処
- 5 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 6 3Dグラフィックスのソフト一覧|Blender・Metasequoiaと用途別の選び方
- 7 Spring Frameworkのアノテーション一覧
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- Visual Studio「デザイナーを表示できません」エラーの原因と対処 2026-10-28 12:06:00
- SSH 認証に失敗しました。再試行してください の対処 2026-10-28 12:06:00
- SSH2 秘密鍵の読み込みに失敗しました の原因と対処 2026-10-28 12:06:00
- TeraTerm のよくあるエラーと対処法完全ガイド — Connection refused / 2026-10-28 12:06:00
- Visual Studio エラー一覧|コンパイルエラー・警告の確認方法と対処 2026-10-28 11:39:57
- Whitelabel Error Page の原因と消し方|Spring Boot のエラーページ 2026-10-28 11:39:57
- Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法 2026-10-28 11:39:57
- SQL WHERE 句完全ガイド 2026-10-28 11:39:57
- SQL JOIN 完全ガイド (INNER/LEFT/RIGHT/FULL OUTER) 2026-10-28 11:39:57
- tomcat の起動 / 停止ログと catalina.log・catalina.out の違い 2026-10-28 10:24:23
- Tomcat の起動確認方法 5 つ|localhost:8080・ポート・プロセス・ログ 2026-10-28 10:24:23
- Oracle 19c COMMITの使い方: 暗黙コミット・自動確定・応答不明時の確認 2026-10-28 09:59:09
- Oracle 19c DELETE文|削除対象の確認・COMMIT前の判断・ROLLBACKの条件 2026-10-28 09:59:09
- Oracle 19c INSERT文|INSERT ALL・SELECT・RETURNINGとMERGEの使い分け 2026-10-28 09:59:09
- Oracle 19cのトランザクション制御|COMMIT・ROLLBACK・分離レベルと接続設定 2026-10-28 09:59:09