# Django 5.2.8 ドキュメント

# ビューを記述する

ビュー関数、つまり view は、Web リクエストを受け取って Web レスポンスを返すPython 関数です。 このレスポンスは、WebページのHTMLコンテンツ、リダイレクトや404エラー、またはXMLドキュメントやイメージ、その他何にでもなり得ます (本当にそうなんです)。ビュー自体には、このレスポンスを返すために必要な、任意の論理が含まれます。 このコードは、Python パス上にあればどこでも好きな場所に置くことができます。それ以外の要件はありません -- つまり "魔法" はないのです。 コードを どこかに 置くために、慣習ではプロジェクトやアプリケーションのディレクトリに置かれた `views.py` というファイルにビューを記述します。

## シンプルなビュー

以下は、HTML ドキュメントとして、現在の日付と時刻を返すビューです:

    from django.http import HttpResponse
    import datetime

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

1 行ずつコードを見ていきましょう:

- 最初に、Python の `datetime` ライブラリ とともに、クラス `HttpResponse` を `django.http` モジュールからインポートします。

- 次に、`current_datetime` という関数を定義します。これがビュー関数です。それぞれのビュー関数は、`HttpRequest` のオブジェクトを第 1 引数として受け取り、一般的には `request` と名付けられます。

  ビュー関数の名前は重要ではありません; Django が識別するために特別な方法で名前を付ける必要はありません。ここでは、`current_datetime` という名前はその機能を的確に表しているので、ビュー関数を `current_datetime` と呼ぶことにします。

- このビューは、生成されたレスポンスを含む `HttpResponse` のオブジェクトを返します。それぞれのビュー関数には、`HttpResponse` オブジェクトを返す義務があります。(例外もありますので、後で説明します。)

Django のタイムゾーン

Django は `TIME_ZONE` 設定を含んでおり、デフォルトは `America/Chicago` です。これはあなたの住む場所ではないかもしれませんので、あなたの設定ファイルを変更する必要があるかもしれません。

## URL をビューにマッピングする

要約すると、このビュー関数は現在の日付と時刻を含む HTML ページを返します。このビューを特定の URL で表示するには、URLconf を作成する必要があります。その方法は、URL ディスパッチャ を参照してください。

## エラーを返す

Django には HTTP エラーコードを返す便利な方法が用意されています。("OK" を意味する) 200 以外の数ある一般的なHTTPステータスコードに対して、`HttpResponse` サブクラスがあります。使用可能なサブクラスの完全なリストは、request/response ドキュメントにあります。エラーを知らせるためには、通常の `HttpResponse` の代わりに、これらのサブクラスのインスタンスを返してください。例えば:

    from django.http import HttpResponse, HttpResponseNotFound

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

レスポンスコードの多くは使用頻度が低いため、発生しうる HTTP レスポンスコードすべてにそれぞれ特化したサブクラスが用意されているわけではありません。 しかし、`HttpResponse` のドキュメントに書かれているように、HTTP ステータスコードをコンストラクタに渡して、`HttpResponse` が任意のステータスコードを返すクラスを作成することもできます。例えば:

    from django.http import HttpResponse

    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
    from django.shortcuts import render
    from polls.models import Poll

    def detail(request, poll_id):
        try:
            p = Poll.objects.get(pk=poll_id)
        except Poll.DoesNotExist:
            raise Http404("Poll does not exist")
        return render(request, "polls/detail.html", {"poll": p})

Django が 404 を返したときに独自の HTML を表示したいときは、`404.html` という名前の HTML テンプレートを作成し、テンプレートツリーのトップレベルの場所に置いてください。`DEBUG` が `False` にセットされているとき、このテンプレートが使われます。

`DEBUG` が `True` の場合、`Http404` にメッセージを提供し、標準的な 404 デバッグテンプレートに表示させることができます。このメッセージ機能はデバッグ用に使用してください; 通常、プロダクトの404 テンプレートとしては不向きです。

## エラービューをカスタマイズする

Django のデフォルトのエラービューは、ほとんどの Web アプリケーションで十分ですが、独自の動作が必要な場合は簡単にオーバーライドできます。 URLconf で以下のようにハンドラを指定してください (他の場所で設定しても効果はありません)。

`page_not_found()` ビューは `handler404` でオーバーライドされます:

    handler404 = "mysite.views.my_custom_page_not_found_view"

`server_error()` ビューは `handler500` でオーバーライドされます:

    handler500 = "mysite.views.my_custom_error_view"

`permission_denied()` ビューは `handler403` でオーバーライドされます:

    handler403 = "mysite.views.my_custom_permission_denied_view"

`bad_request()` ビューは `handler400` でオーバーライドされます:

    handler400 = "mysite.views.my_custom_bad_request_view"

参考

CSRF エラービューをオーバーライドするには、`CSRF_FAILURE_VIEW` 設定を使用してください。

### カスタムエラービューのテスト

カスタムエラーのハンドラーのレスポンスをテストするには、たとえば以下のように、テストビューの中で適切な例外を起こします。

    from django.core.exceptions import PermissionDenied
    from django.http import HttpResponse
    from django.test import SimpleTestCase, override_settings
    from django.urls import path

    def response_error_handler(request, exception=None):
        return HttpResponse("Error handler content", status=403)

    def permission_denied_view(request):
        raise PermissionDenied

    urlpatterns = [
        path("403/", permission_denied_view),
    ]

    handler403 = response_error_handler

    # ROOT_URLCONF must specify the module that contains handler403 = ...
    @override_settings(ROOT_URLCONF=__name__)
    class CustomErrorHandlerTests(SimpleTestCase):
        def test_handler_renders_template_response(self):
            response = self.client.get("/403/")
            # Make assertions on the response here. For example:
            self.assertContains(response, "Error handler content", status_code=403)

## 非同期ビュー

同期関数だけでなく、ビューは非同期("async")関数にすることもでき、通常は Python の `async def` 構文を使って定義します。Django はこれらを自動的に検出し、非同期コンテキストで実行します。しかし、そのパフォーマンス上の利点を得るには、 ASGI ベースの非同期サーバを使う必要があります。

以下は非同期ビューの例です:

    import datetime
    from django.http import HttpResponse

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

Django の非同期サポートや、非同期ビューの最適な使い方については、 非同期サポート を参照してください。