こんにちは、かつコーチです。
前回の記事でurls.pyからviews.pyの処理を呼び出す流れを紹介しましたが、今回はその「処理」そのものを担当するViewの書き方を詳しく解説します。
Djangoには2種類のViewの書き方があり、その1つが今回扱う関数ベースビュー(FBV: Function-Based View)です。
関数ベースビューとは?
関数として定義するシンプルなView
関数ベースビュー(FBV)とは、その名の通り、Pythonの関数としてViewを定義する書き方です。
リクエストを受け取り、何らかの処理をして、レスポンスを返す、という一連の流れを1つの関数の中に素直に書けるのが特徴です。
# blog/views.py
from django.http import HttpResponse
def index(request):
return HttpResponse("こんにちは、Djangoの世界へ")
引数のrequestには、ブラウザから送られてきたリクエストの情報(GETパラメータ、POSTデータ、ユーザー情報など)がすべて詰まっています。
もう1つの書き方「クラスベースビュー(CBV)」との違い
DjangoにはFBVのほかに、クラスベースビュー(CBV: Class-Based View)という書き方も用意されています。
CBVはクラスを使ってViewを定義する方法で、共通処理をまとめやすいというメリットがありますが、初心者にはやや抽象度が高く感じられることがあります。
| 項目 | FBV | CBV |
|---|---|---|
| 書き方 | 関数 | クラス |
| 可読性 | 処理の流れが上から下に追いやすい | 継承関係を理解する必要がある |
| 向いている場面 | シンプルな処理、条件分岐が複雑な処理 | 一覧・詳細・作成・更新など定型的な処理 |
まずはFBVで「Viewが何をしているか」を体で理解してから、CBVに進むのがおすすめの学習順序です。
CBVの詳しい使い方は、この後の記事「クラスベースビュー(CBV)の基本と使いどころ」で扱います。
FBVの基本の書き方
GETリクエストを処理する
まずは最もシンプルな、一覧ページを表示するFBVを書いてみましょう。
# blog/views.py
from django.shortcuts import render
def index(request):
context = {
"title": "ブログ記事一覧",
"posts": ["1本目の記事", "2本目の記事", "3本目の記事"],
}
return render(request, "blog/index.html", context)
render()関数は、指定したテンプレートにcontext(テンプレートに渡すデータの辞書)を渡してHTMLを組み立て、レスポンスとして返してくれる便利な関数です。
テンプレート側では、次のようにcontextに渡したデータを表示できます。
<!-- blog/templates/blog/index.html -->
<h1>{{ title }}</h1>
<ul>
{% for post in posts %}
<li>{{ post }}</li>
{% endfor %}
</ul>
リクエストメソッドで処理を分岐する
フォームの送信を受け取るViewでは、GETとPOSTで処理を分けるのが基本パターンです。
# blog/views.py
from django.shortcuts import render, redirect
def contact(request):
if request.method == "POST":
name = request.POST.get("name")
# 本来はここでバリデーションや保存処理を行う
return redirect("blog:index")
return render(request, "blog/contact.html")
request.methodで現在のリクエストがGETかPOSTかを判定し、request.POST.get("name")のようにフォームから送られてきたデータを取得します。
404エラーを自分で制御する
存在しないデータへのアクセスに対しては、get_object_or_404を使うと簡潔に書けます。
# blog/views.py
from django.shortcuts import render, get_object_or_404
from .models import Post
def detail(request, pk):
post = get_object_or_404(Post, pk=pk)
return render(request, "blog/detail.html", {"post": post})
get_object_or_404は、指定したデータが存在すればそのまま返し、存在しなければ自動的に404エラーページを表示してくれる便利な関数です。
つまずきやすい設定・注意点
render()の第2引数のパス指定を間違える
テンプレートのパス指定でつまずくケースはとても多いです。
Djangoはsettings.pyのTEMPLATES設定に基づいてテンプレートを探すため、アプリ名を含めたフォルダ構成にしておくのが一般的です。
blog/
└── templates/
└── blog/ ← アプリ名と同じ名前のフォルダを挟む
└── index.html
このように、あえてblog/templates/blog/と2階層にアプリ名を重ねるのが慣習になっています。
これを知らずにblog/templates/index.htmlと直接置いてしまうと、別のアプリの同名テンプレートと衝突するリスクがあるため注意が必要です。
よくあるつまずきポイント・エラー対処
TemplateDoesNotExistエラーが出る
❌ Before
TemplateDoesNotExist at /blog/
blog/index.html
これは、テンプレートファイルが見つからない、もしくはフォルダ構成が間違っているときに出るエラーです。
✅ After
# config/settings.py のINSTALLED_APPSに、
# テンプレートを持つアプリ(blog)が登録されているか確認する
INSTALLED_APPS = [
# ...
"blog",
]
筆者もこのエラーに何度も遭遇しましたが、原因のほとんどは「アプリをINSTALLED_APPSに登録し忘れている」か「テンプレートのフォルダ階層を間違えている」のどちらかでした。
エラーが出たら、まずこの2点を疑うと解決が早くなります。
request.POST.get()の代わりにrequest.POST[]を使ってエラーになる
❌ Before
name = request.POST["name"]
# KeyError: 'name'
# フォームにname項目がない場合、そのままエラーで落ちてしまう
✅ After
name = request.POST.get("name", "")
# 項目がなくても空文字を返し、エラーにならない
request.POST["name"]は辞書のキーアクセスと同じ書き方のため、キーが存在しないとその場でエラーになります。get()メソッドを使い、デフォルト値を指定しておくと、想定外の入力に対しても安全に処理できます。
応用・一歩先の使い方
デコレータでアクセス制限をかける
FBVは関数なので、デコレータ(関数の前後に処理を付け加える仕組み)を使って、ログインしていないユーザーのアクセスを制限するといったことも簡単に書けます。
# blog/views.py
from django.contrib.auth.decorators import login_required
@login_required
def create(request):
return render(request, "blog/create.html")
@login_requiredを付けるだけで、未ログインのユーザーがアクセスした場合は自動的にログインページへリダイレクトされます。
このシンプルさは、関数ベースビューならではの書きやすさと言えるでしょう。
まとめ
この記事のポイント
- 関数ベースビュー(FBV)は、Viewを素直な関数として定義する書き方
render()でテンプレートにデータを渡し、request.methodでGET/POSTを判定する- テンプレートは「アプリ名/templates/アプリ名/」の2階層構成にするのが慣習
get_object_or_404やデコレータを使うと、定型処理を簡潔に書ける
次に読むべき記事
FBVの書き方が分かったら、次はもう1つのViewの書き方である「クラスベースビュー(CBV)の基本と使いどころ」に進み、定型的な処理をより効率的に書く方法を学んでいきましょう。
タグ: Django, 初心者向け, フレームワーク基礎