1.

djangoのクラスベースビュー作り方とviewの分割方法

▶

クラスベースビューを機能別ファイルへ分け、URLとの接続を確認する手順です。FBVとCBVはどちらも使える方式で、どちらが主流かではなく処理と再利用の必要性で選びます。

projectのURL設定からapp1のURL設定を経て関数またはas_viewで分割ビューへ接続する流れ

この記事の要点
  • Django のクラスベースビュー (CBV) の作り方と view 分割
  • 基本: from django.views.generic import View を継承し def get(self, request, ...) / def post(...) を定義
  • URL ディスパッチ: TestView.as_view() を urls.py に渡す
  • view が増えたら views/ ディレクトリ + 機能別ファイルに分割

 

以下、デフォルトのディレクトリ構造

プロジェクト名/
    db.sqlite3
    manage.py
   
プロジェクト名/
        __init__.py
        settings.py
       
urls.py
        wsgi.py
   
アプリケーション名/
        __init__.py
        __pycache__/
        admin.py
        apps.py
        migrations/
        models.py

        views.py

1アプリケーションに1ビューという制限はありません。標準のviews.pyはPythonの1モジュールで、複数の関数やクラスを置けます。短い処理なら無理に分割せず、機能別の責務やテストの読みやすさで分割を決めます。旧図はASGI等を省いた構成例で、Djangoが全ファイルを自動生成するという意味ではありません。

それを以下のように修正する。

 プロジェクト名/
    db.sqlite3
    manage.py
   
プロジェクト名/
        __init__.py
        settings.py
       
urls.py
        wsgi.py

    アプリケーション名/
        __init__.py
        __pycache__/
        admin.py
        apps.py
        migrations/
        models.py
       
urls.py

        templates

                index.html

                test.html

        views

                index.py

                test.py

既存のviews.pyを内容ごと削除しないでください。変更前のコードを版管理や別の退避先へ保存し、既存関数・クラス・import・デコレーター・URL名を棚卸しします。処理をviews/内の各モジュールへ移してimportを更新し、確認後に切り替えます。同じapp1にviews.pyとviews/を残してどちらが読まれるかに依存せず、切替後はviews/へ一本化します。この記事の例で既存プロジェクトのファイルを丸ごと上書きしません。

その中に分割したviewファイル(上記の例では index.py および test.py)を作成する。

更にアプリケーション名ディレクトリ直下にurls.pyを作成してルーティング処理を記載する。

プロジェクト名ディレクトリ直下のurls.pyを修正する必要もある。

また、簡単ではあるが表示用のテンプレートにindex.htmlおよびtest.htmlをtemplatesディレクトリを作成してその配下に配置する。

以下、それぞれのファイルの詳細を記述する。

今回のアプリケーション名は「app1」とします。

 

動かす前に揃える設定

追加例はPython 3.12 / Django 5.2系の独立した学習用プロジェクトです。プロジェクトのPythonパッケージ名をproject、アプリ名をapp1とします。manage.pyのあるディレクトリを基準に配置し、project/__init__.py・app1/__init__.py・app1/views/__init__.pyは空で用意します。__pycache__は手で作りません。既存設定は保持して必要箇所だけ照合します。

次は新しい学習用構成の断片です。既存のINSTALLED_APPSやTEMPLATESをこの短いリストで置き換えず、既存アプリ・loader・context_processors・MIDDLEWAREのCSRF/認証設定は保持してください。

ROOT_URLCONF = "project.urls"
INSTALLED_APPS = ["app1"]
TEMPLATES = [{
    "BACKEND": "django.template.backends.django.DjangoTemplates",
    "DIRS": [],
    "APP_DIRS": True,
    "OPTIONS": {"context_processors": []},
}]

これはsettings.pyへ照合する断片で、秘密鍵・許可Host・DB・認証等を含む本番設定一式ではありません。ROOT_URLCONFはファイルパスでなくimport可能なPythonモジュール名です。APP_DIRS=Trueは登録したアプリのtemplates/を探します。INSTALLED_APPSへapp1を追加するだけではURLへ接続されないため、project.urlsのincludeも必要です。表示だけの例なのでmigrateや実DBの更新は不要です。

分割したviewファイル

index.py

from django.views.generic import TemplateView

class IndexView(TemplateView):

    template_name = "index.html"

 

test.py

from django.views.generic import TemplateView

class TestView(TemplateView):

    template_name = "test.html"

 

追加例:明示的なimportで使う2つのビュー

app1/views/index.py

from django.views.generic import TemplateView


class IndexView(TemplateView):
    template_name = "app1/index.html"

app1/views/test.py

from django.views.generic import TemplateView


class TestView(TemplateView):
    template_name = "app1/test.html"

TemplateViewはテンプレート表示用の汎用CBVです。任意のget/postを実装する基底Viewと区別します。GETをHEADにも用い、postを実装していないこの例はPOSTを処理しません。as_view()はURLへ渡す呼出し可能オブジェクトを返し、クラスを直接渡したりas_view自体を渡したりするのとは異なります。各リクエストのインスタンスと、共有され得るクラス属性やas_view引数の可変オブジェクトを混同しないでください。

アプリケーション名直下のurls.py

from django.urls import path
from app1.views.index import IndexView
from app1.views.test import TestView

urlpatterns = [

    path('', IndexView.as_view()),

    path('test/', TestView.as_view()),

]

 

追加例:app1/urls.py

from django.urls import path
from .views.index import IndexView
from .views.test import TestView

app_name = "app1"
urlpatterns = [
    path("", IndexView.as_view(), name="index"),
    path("test/", TestView.as_view(), name="test"),
]

app_nameとnameによりreverse("app1:index")は/app1/、reverse("app1:test")は/app1/test/を返します。ファイルを分割しても公開パスは維持できます。ただし既存のindex等を名前空間なしで逆引きしているプロジェクトへapp_nameを後付けする場合は、呼出し側のURL名も更新・確認します。パス維持とURL名の互換性は別です。

プロジェクト名直下のurls.py

追加例のproject/urls.pyは次の通りです。既存の管理画面や他アプリのパターンを消さず、app1へのincludeだけを追加・確認します。includeは一致したapp1/を除く残りのパスをアプリ側へ渡します。

from django.urls import include, path

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

保存用の旧project URLconfも残しています。上書き用の完全な既存設定ではありません。

from django.contrib import admin

from django.urls import include, path

urlpatterns = [

    path('app1/', include('app1.urls')),

]
 

 

■ルートのURLconfを指定します

保存用の旧設定ROOT_URLCONF = 'urls'は標準startproject構成へそのまま適用しません。project/urls.pyならproject.urlsです。トップレベルurls.pyを独自配置している構成とは区別します。追加例のsettings断片と実際のPythonパッケージ名を照合してください。

プロジェクト名/settings.py

ROOT_URLCONF = 'urls'

 

 

テンプレート

旧例はindex.html/test.htmlという一般名です。複数アプリで同名が衝突しないよう、追加例はapp1/templates/app1/へ配置し、template_nameもapp1/index.html・app1/test.htmlに揃えます。ファイルを移すだけでは直りません。実際の探索先と名前を同時に確認します。

追加例:アプリ名で区切るテンプレート

app1/templates/app1/index.html

<!doctype html>
<html lang="ja">
<meta charset="utf-8">
<title>Index</title>
<p>index {{ view_name|default:"page" }}</p>
</html>

app1/templates/app1/test.html

<!doctype html>
<html lang="ja">
<meta charset="utf-8">
<title>Test</title>
<p>test {{ view_name|default:"page" }}</p>
</html>

この2例の変数はDjangoの通常のHTMLエスケープを使います。autoescape offやsafeを足さず、HTML本文のエスケープをJavaScript/URL等の全出力文脈の保護と同一視しません。

元の記事のテンプレート例

index.html

index

 

test.html

test

 

以上で以下のURLをアクセスすることで異なるviewにアクセスすることができます。

http://127.0.0.1:8000/app1/

http://127.0.0.1:8000/app1/test/

切替後の確認と、開けない場合の調べ方

  1. 対象プロジェクトの仮想環境でpython manage.py checkを実行し、importとURL定義のエラーを確認します。checkの成功だけでは実際の応答や権限を保証しません。
  2. 開発用の127.0.0.1で/app1/と/app1/test/のGET、別URLの404、HEADとPOSTを個別に確認します。本番公開やroot起動は行いません。
  3. 404ならproject.urlsのinclude、app側のパスと末尾スラッシュ、実際の開始URLを照合します。APPEND_SLASHのリダイレクトでPOST本文が保たれると仮定しません。
  4. ImportError/AttributeErrorならPythonの配置とimport対象、views.pyとviews/の混在や循環importを確認します。__init__.pyで全ビューを一括importして依存を増やさないようにします。
  5. TemplateDoesNotExistならtemplate_name、アプリ登録、APP_DIRS/DIRSと実ファイル位置を確認します。403はCSRF/権限、405はHTTPメソッドの受け付けを切り分け、csrf_exemptでエラーを隠しません。
  6. 旧URL・名前付き逆引き・デコレーター/認証・応答本文のテストを通してから切り替えます。ファイル移動だけで既存のログイン/権限処理が移るとは限りません。

公開データの更新や認証・フォーム保存はこの表示用例の対象外です。自作のパッケージをdjango.pyやhttp.pyと命名して標準/外部モジュールを隠さないことも確認します。関数とクラスを混在させても構いません。

関連する既存ページ

ビューの親ページ、URLディスパッチャー、関数ベースビュー、CBVのGET/POST、開発サーバーの待受とポートを目的に合わせて選んでください。

根拠と検証範囲(2026年10月26日)

Django公式:ビュー、CBVの導入、URLの接続と名前空間、View/TemplateView、テンプレート探索を確認しました。追加例はPython3.12.10/Django5.2.18の隔離環境でURL解決/逆引き・実際の表示/HEAD/POST・CSRF・テンプレート探索・同名関数の上書きを検査しています。実DBへの書込み・本番配備・認証/全middleware・他の版・ASGI非同期処理は未検証です。

子ページ

子ページはありません

同階層のページ
  1. クラスベースビューの作り方とviewの分割
  2. 関数ベースビューの作り方とviewの分割
  3. URLディスパッチャー(ルーティング処理)
  4. GETとPOSTパラメータ受け取り
  5. クラスベースビューでGET/POSTリクエストの受け取り方
  6. クラスベースビューでテンプレートに値を渡す方法
  7. ビューでリダイレクト
  8. cookieの値の設定と取得
  9. HTTPステータスコードの返し方

最近更新/作成されたページ