ビューを書く

revision-up-to:17812 (1.4)

ビュー関数、あるいは単に ビュー とは、簡単にいえばウェブリクエストを引数 にとり、ウェブレスポンスを返す関数です。レスポンスはウェブページを表す HTML コンテンツでもよいし、リダイレクトでも、 404 エラーでも、 XML ドキュメント でも、画像でも、何でもかまいません。ビューの中には、レスポンスを生成する上 で必要なロジックを自由に書けます。ビューのコードは、 Python パス上にあるか ぎり、どこに置いてもかまいません。他にはなんの制限も「黒魔術」もありません。 慣習では、 プロジェクトディレクトリかアプリケーションディレクトリの下に views.py という名前のファイルを作成して、そこにビューのコードを置くこと になっています。

簡単なビュー

以下に示すのは、現在の日付や時刻を HTML 形式で返すビューの例です:

from django.http import HttpResponse
import datetime

def current_datetime(request):
    now = datetime.datetime.now()
    html = "<html><body>It is now %s.</body></html>" % now
    return HttpResponse(html)

Let’s step through this code one line at a time:

  • まず、 django.http モジュールから HttpResponse クラスを import しています。 Python の datetime ライブラリもロードしておきます。

  • 次に、 current_datetime という関数を定義しています。これがビュー 関数です。ビュー関数は第一引数に HttpRequest オブジェクトを取ります。慣習的に、この引数の名前は request にして います。

    ビュー関数はどんな名前でもかまいません。Django にビュー関数として認識 してもらうために、何らかの特殊な命名規則に従う必要はないのです。ここ では、 current_datetime という名前を付けて、どんな機能のビューか 分かりやすくしています。

  • ビューは、生成したレスポンスコンテンツの入った HttpResponse オブジェクトを返します。ビュー関数 は HttpResponse オブジェクトを返さねばなりません (例外も返してよ いのですが、それについては後で説明します)。

Django のタイムゾーン設定

Django には TIME_ZONE 設定があり、デフォルト値は America/Chicago に設定されています。お住まいの地域がここでなければ、 変更しておいてください。

URL をビューにマップする

このビュー関数は、現在の日付と時刻が入った HTML ページを生成して返します。 何らかの URL でこのビューを表示したければ、 URLconf を作成する必要があり ます。 URL ディスパッチャ の説明を読んでください。

エラーを返す

Django では、簡単に HTTP エラーコードを返せます。エラー応答は、すでに述べた HttpResponseNotFound, HttpResponseForbidden, HttpResponseServerError といったサブクラスのインスタンスを作成して、 以下の例のように通常の HttpResponse の代わりに返すだ けです:

def my_view(request):
    # ...
    if foo:
        return HttpResponseNotFound('<h1>Page not found</h1>')
    else:
        return HttpResponse('<h1>Page was found</h1>')

全ての HTTP レスポンスコードごとに特別なサブクラスがあるわけではありません。 多くは共通化できるからです。しかし HttpResponse のドキ ュメントにあるように、 HttpResponse のコンストラクタに HTTP ステータスコードを渡すことで、好きなステータスコードを返すクラスを作れ ます。例:

def my_view(request):
    # ...

    # Return a "created" (201) response code.
    return HttpResponse(status=201)

ただし、 404 エラーは他の HTTP エラーよりはるかに良く使われるエラーなので、 もっと簡単に扱う方法を提供しています。

Http404 例外

class django.http.Http404

HttpResponseNotFound` のようなエラーを返す場合、以下 のように、エラーページの中身になる HTML を指定せねばなりません:

return HttpResponseNotFound('<h1>Page not found</h1>')

これはちょっと不便ですね。それに、サイト全体で一貫した 404 エラーページを用 意しておく方が賢明です。そこで、 Django には Http404 例外があります。 ビュー関数のどこかで Http404 例外を送出すると、 Django はこのエラーを捕 捉して、サイト標準のエラーページを HTTP エラーコード 404 で返します。

例を示しましょう:

from django.http import Http404

def detail(request, poll_id):
    try:
        p = Poll.objects.get(pk=poll_id)
    except Poll.DoesNotExist:
        raise Http404
    return render_to_response('polls/detail.html', {'poll': p})

Http404 例外を使うには、 404 エラーの送出時に表示されるテンプレートを作 成しておかねばなりません。このテンプレートの名前は 404.html で、テンプ レートツリーの一番上に配置せねばなりません。

エラービューのカスタマイズ

404 (ページが見つかりません) ビュー

Http404 例外を送出すると、 Django は 404 エラー処理用の特殊なビューをロー ドします。デフォルトでは、このビューは django.views.defaults.page_not_found に設定されています。 django.views.defaults.page_not_found404.html という名前のテンプ レートをロードしてレンダします。

このため、テンプレートディレクトリの再上階層に 404.html という名前のテ ンプレートを作成しておかねばなりません。このテンプレートは全ての 404 エラー に対して用いられます。デフォルトの 404 ビューはテンプレートに request_path という変数を渡します。これはエラーになった URL です。

page_not_found ビューは 99% の Web アプリケーションの要求を満たすはずで

すが、 404 ビューを自作したい場合には、URLconf で以下のようにして handler404 を指定します:

handler404 = 'mysite.views.my_custom_404_view'

舞台裏では、 Django はルート URLconf の handler404 を介して 404 ビューを 捜し出します。定義がなければ django.views.defaults.page_not_found にフォ ールバックします。

404 ビューについて、知っておかねばならないことが 4 つあります:

  • 404 ビューは、リクエストされた URL に対して、 Django が URLconf の全 ての正規表現を調べた結果、一致するものをみつけられなかった場合にも呼 び出されます。
  • 404 ビューを自作せず、ただデフォルトのビューを使う場合でも、一つだけ やらねばならないこととして、 404.html という名前のテンプレートを 作成せねばなりません。
  • 404 ビューに渡されるコンテキストは django.template.RequestContext なので、テンプレートには TEMPLATE_CONTEXT_PROCESSORS で追加した変数も 渡ります。 (例えば MEDIA_URL)
  • (settings モジュールで) DEBUGTrue にすると、 404 ビューは 呼び出されず、代わりにトレースバックが表示されます。

500 (サーバエラー) ビュー

404 エラーと同様に、 Django はビューのコード上で実行時エラーに遭遇した場合 の挙動も特別扱いしています。ビューを実行した結果、例外が送出されると、 Django はデフォルトで django.views.defaults.server_error というビューを 呼び出します。このビューは 500.html というテンプレートをロードしてレン ダします。

このため、テンプレートディレクトリの再上階層に 500.html という名前のテ ンプレートを作成しておかねばなりません。このテンプレートは全ての 500 エラー に対して用いられます。デフォルトの 500 ビューはテンプレートに一切変数を渡さ ず、空の Context インスタンスを渡してレンダリングを実行しますが、これは さらなるエラーが発生するのを防ぐためです。

server_error ビューは 99% の Web アプリケーションの要求を満たすはずです が、 500 ビューを自作したい場合には、URLconf で以下のようにして handler500 を指定します:

handler500 = 'mysite.views.my_custom_error_view'

舞台裏では、 Django はルート URLconf の handler500 を介して 500 ビューを 捜し出します。何も定義していなければ、 django.views.defaults.server_error にフォールバックします。

500 ビューについて、知っておかねばならないことが 2 つあります:

  • 500 ビューを自作せず、ただデフォルトのビューを使う場合でも、一つだけ やらねばならないこととして、 500.html という名前のテンプレートを 作成せねばなりません。
  • (settings モジュールで) DEBUGTrue にすると、 500 ビューは 呼び出されず、代わりにトレースバックが表示されます。

403 (閲覧が禁止されています) ビュー

Django 1.4 で新たに登場しました: リリースノートを参照してください

404 ビュー、 500 ビューと同じスタイルで、 Django は 403 Forbidden エラーを 処理するためのビューを持っています。ビューが 403 例外を起こしたら、 Django はデフォルトでは django.views.defaults.permission_denied ビューを呼びま す。

このビューは 403.html テンプレートを最上階層のテンプレートディレクトリ からロードし、レンダします。ファイルがない場合、 RFC 2616 (HTTP 1.1 仕様) により “403 Forbidden” テキストを返します。

404 や 500 ビューと同じように、 handler403 を URLconf に設定することで django.views.defaults.permission_denied をオーバーライドできます:

handler403 = 'mysite.views.my_custom_permission_denied_view'