Django の関数ビューとクラスベースビューの違い

Django でリクエストを受け取りレスポンスを返す処理を書く場所がビューです。ビューには関数で書く方法(FBV)とクラスで書く方法(CBV)の 2 つがあり、どちらも同じことができますが、得意な場面が異なります。

関数ビュー(FBV)の基本

関数ビューは、リクエストオブジェクトを受け取って HttpResponse を返す関数です。

from django.http import HttpResponse
from django.shortcuts import render

def article_list(request):
    articles = Article.objects.filter(is_draft=False)
    return render(request, 'articles/list.html', {
        'articles': articles
    })

render はテンプレートにコンテキスト(変数の辞書)を渡して HTML を生成するショートカット関数です。戻り値は HttpResponse オブジェクトになります。

HTTP メソッドによる分岐は request.method で判定します。

def article_create(request):
    if request.method == 'POST':
        form = ArticleForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('article_list')
    else:
        form = ArticleForm()
    return render(request, 'articles/create.html', {'form': form})

関数ビューはロジックの流れが上から下に一直線で読めるため、処理の全体像を把握しやすいのが利点です。

クラスベースビュー(CBV)の基本

クラスベースビューは View クラスを継承し、HTTP メソッドに対応するメソッドを定義する方式です。

from django.views import View
from django.shortcuts import render, redirect

class ArticleCreateView(View):
    def get(self, request):
        form = ArticleForm()
        return render(request, 'articles/create.html', {'form': form})

    def post(self, request):
        form = ArticleForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('article_list')
        return render(request, 'articles/create.html', {'form': form})

if request.method == 'POST' の分岐が不要になり、GET と POST の処理がメソッドとして自然に分離されます。

URL の設定では .as_view() を呼び出します。

from django.urls import path
from .views import ArticleCreateView

urlpatterns = [
    path('articles/create/', ArticleCreateView.as_view(), name='article_create'),
]

汎用ビューで定型処理を省略する

Django には ListViewDetailViewCreateView など、よくあるパターンを数行で実現できる汎用クラスベースビューが用意されています。

from django.views.generic import ListView

class ArticleListView(ListView):
    model = Article
    template_name = 'articles/list.html'
    context_object_name = 'articles'
    queryset = Article.objects.filter(is_draft=False)

モデルとテンプレートを指定するだけで、一覧取得・テンプレートへの受け渡し・レスポンスの返却をすべて自動で処理してくれます。

関数ビュー(FBV)

処理の流れが明示的で読みやすい。小規模な処理やカスタムロジックが多い場面に向く

クラスベースビュー(CBV)

定型パターンを短いコードで実現できる。汎用ビューとの組み合わせで CRUD 画面を効率的に作れる

URL の設定方法の違い

関数ビューはそのまま関数を渡し、クラスベースビューは .as_view() を通す必要があります。

from django.urls import path
from . import views

urlpatterns = [
    # 関数ビュー
    path('articles/', views.article_list, name='article_list'),

    # クラスベースビュー
    path('articles/', views.ArticleListView.as_view(), name='article_list'),
]

.as_view() はクラスをインスタンス化し、リクエストのメソッドに応じて get()post() にディスパッチする仕組みです。この変換があるため、Django の URL ルーティングは関数ビューでもクラスベースビューでも同じ path() で統一的に扱えます。

どちらを選ぶべきか

Django の公式ドキュメントはどちらか一方を推奨していません。実務ではプロジェクト内で混在させることも珍しくなく、画面の性質に応じて使い分けるのが現実的です。

関数ビューが向く場面

API のエンドポイントなど、1 つの関数で完結する短い処理。条件分岐が複雑で、汎用ビューのフックに収まらないカスタムロジック。

クラスベースビューが向く場面

CRUD 操作の一覧・詳細・作成・更新・削除を汎用ビューで効率よく作りたいとき。共通処理を Mixin で再利用したいとき。

最初は関数ビューから入り、定型パターンが増えてきたらクラスベースビューに移行する——という流れが最もスムーズです。どちらも Django のビューとして等価なので、チームの方針やプロジェクトの規模に合わせて柔軟に選択してください。