1.

Django View 完全ガイド — FBV と CBV

編集
この記事の要点
  • Django の View は HTTP リクエストを受け取り HTTP レスポンスを返す「コントローラ」。views.py に書く
  • 書き方は 2 種類: Function-based View (FBV)Class-based View (CBV)
  • レスポンス: HttpResponse / render(request, "app/index.html", context) / redirect("name") / JsonResponse
  • ジェネリック CBV: ListView / DetailView / CreateView / UpdateView / DeleteView で CRUD が数行で書ける
  • URL マッピングは urls.pypath()。デコレータ @login_required / @require_http_methods で認証・メソッド制限

View とは

Django MVT (Model-View-Template) パターンの「View」は、Web リクエストを受け取り、必要な処理を実行してレスポンスを返す Python 関数 / クラスです。他フレームワークでいう Controller に相当します。

View は views.py に書き、urls.py で URL とマッピングします。

Function-based View (FBV) — 最も基本

# myapp/views.py
from django.http import HttpResponse
from django.shortcuts import render, redirect, get_object_or_404
from .models import Article

# 最小の View
def hello(request):
    return HttpResponse("Hello, Django!")

# テンプレートをレンダー
def index(request):
    articles = Article.objects.all()
    return render(request, "myapp/index.html", {"articles": articles})

# 詳細ページ
def detail(request, article_id):
    article = get_object_or_404(Article, pk=article_id)
    return render(request, "myapp/detail.html", {"article": article})

# POST 処理 + リダイレクト
def create(request):
    if request.method == "POST":
        Article.objects.create(
            title=request.POST["title"],
            body=request.POST["body"],
        )
        return redirect("myapp:index")
    return render(request, "myapp/create.html")

URL マッピング

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

app_name = "myapp"
urlpatterns = [
    path("", views.index, name="index"),
    path("hello/", views.hello, name="hello"),
    path("article//", views.detail, name="detail"),
    path("create/", views.create, name="create"),
]

# プロジェクト全体の urls.py
# project/urls.py
from django.urls import include, path
urlpatterns = [
    path("myapp/", include("myapp.urls")),
]

Class-based View (CBV)

クラスベースは再利用性が高く、ミックスインで認証・権限・ページネーションを足せます。

# myapp/views.py
from django.views import View
from django.shortcuts import render, redirect
from .models import Article

class HelloView(View):
    def get(self, request):
        return render(request, "myapp/hello.html")

    def post(self, request):
        # POST 処理
        return redirect("myapp:index")

# urls.py 側
# path("hello/", views.HelloView.as_view(), name="hello"),

ジェネリック CBV — 最強の生産性

CRUD で頻出のパターンを Django が用意してくれています:

ジェネリック View用途テンプレート規約
ListView一覧app/model_list.html
DetailView詳細app/model_detail.html
CreateView新規作成app/model_form.html
UpdateView編集app/model_form.html
DeleteView削除app/model_confirm_delete.html
TemplateView静的ページ任意
RedirectViewリダイレクトテンプレート不要
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
from django.urls import reverse_lazy
from .models import Article

class ArticleListView(ListView):
    model = Article
    paginate_by = 20                 # ページネーション
    ordering = ["-created_at"]        # 降順

class ArticleDetailView(DetailView):
    model = Article

class ArticleCreateView(CreateView):
    model = Article
    fields = ["title", "body"]
    success_url = reverse_lazy("myapp:index")

class ArticleUpdateView(UpdateView):
    model = Article
    fields = ["title", "body"]
    success_url = reverse_lazy("myapp:index")

class ArticleDeleteView(DeleteView):
    model = Article
    success_url = reverse_lazy("myapp:index")

レスポンスの種類

関数 / クラス用途
HttpResponse(text)素のレスポンス
render(request, template, context)HTML テンプレートをレンダー
redirect(name_or_url)リダイレクト (302)
JsonResponse({...})JSON 返却 (Content-Type 自動)
HttpResponseNotFound404
HttpResponseForbidden403
get_object_or_404(Model, pk=id)取得失敗で 404
FileResponse(open(...))ファイルダウンロード

デコレータで認証 / メソッド制限

from django.contrib.auth.decorators import login_required, permission_required
from django.views.decorators.http import require_http_methods, require_POST, require_GET
from django.views.decorators.csrf import csrf_exempt

@login_required
def my_page(request):
    return render(request, "myapp/mypage.html")

@require_POST
def post_only(request):
    # GET でアクセスすると 405 Method Not Allowed
    pass

@require_http_methods(["GET", "POST"])
@login_required
def secure_view(request):
    pass

@permission_required("myapp.delete_article")
def admin_only(request):
    pass

# CBV の場合
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin

class SecureView(LoginRequiredMixin, View):
    login_url = "/login/"

    def get(self, request):
        return render(request, "myapp/secure.html")

FBV vs CBV — どちらを選ぶ?

観点FBVCBV
学習コスト低い (Python 関数)中 (継承・MRO の理解)
コード量多い (CRUD)少ない (ジェネリック)
柔軟性高い中 (定石を外すと面倒)
再利用低い高い (ミックスイン)
おすすめ独自処理、API エンドポイント典型的な CRUD

FAQ

Q: View で DB を直接叩いて良い?
A: 単純な処理なら OK。複雑なビジネスロジックは services.py 等に切り出して View は薄く保つのが定石。

Q: API エンドポイントは何を使う?
A: Django REST Framework の APIView / ViewSet を使うとシリアライザ・パーミッション・ページネーションが揃って便利。

Q: 404 と 500 を独自テンプレートにするには?
A: templates/404.html / 500.html を配置し、settings.pyDEBUG = False + ALLOWED_HOSTS を設定すれば自動表示。

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