---
title: "ビューを記述する"
version: 2.2
locale: ja
source: https://docs.djangoproject.com/ja/2.2/topics/http/views/
canonical: https://djangodocs.dev/ja/2.2/topics/http/views/
---
# ビューを記述する

ビュー関数、つまり *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><body>It is now %s.</body></html>" % now
    return HttpResponse(html)
```

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

- 最初に、Python の `datetime` ライブラリ とともに、クラス [`HttpResponse`](/ja/2.2/ref/request-response/#django.http.HttpResponse) を [`django.http`](/ja/2.2/ref/request-response/#module-django.http) モジュールからインポートします。
- 次に、`current_datetime` という関数を定義します。これがビュー関数です。それぞれのビュー関数は、[`HttpRequest`](/ja/2.2/ref/request-response/#django.http.HttpRequest) のオブジェクトを第 1 引数として受け取り、一般的には `request` と名付けられます。

  ビュー関数の名前は重要ではありません; Django が識別するために特別な方法で名前を付ける必要はありません。ここでは、`current_datetime` という名前はその機能を的確に表しているので、ビュー関数を `current_datetime` と呼ぶことにします。
- このビューは、生成されたレスポンスを含む [`HttpResponse`](/ja/2.2/ref/request-response/#django.http.HttpResponse) のオブジェクトを返します。それぞれのビュー関数には、[`HttpResponse`](/ja/2.2/ref/request-response/#django.http.HttpResponse) オブジェクトを返す義務があります。(例外もありますので、後で説明します。)

> **Django のタイムゾーン**
>
> Django は [`TIME_ZONE`](/ja/2.2/ref/settings/#std-setting-TIME_ZONE) 設定を含んでおり、デフォルトは `America/Chicago` です。これはあなたの住む場所ではないかもしれませんので、あなたの設定ファイルを変更する必要があるかもしれません。

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

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

## エラーを返す

Django で HTTP エラーコードを返すのは簡単です。(*"OK"* を意味する) 200 以外の数ある一般的なHTTPステータスコード（\* "OK" を意味します）に対して、[`HttpResponse`](/ja/2.2/ref/request-response/#django.http.HttpResponse) サブクラスがあります。 使用可能なサブクラスの完全なリストは、request/response \<ref-httpresponse-subclasses\>\`ドキュメントにあります。 エラーを知らせるためには、通常の :class:\`~django.http.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`](/ja/2.2/ref/request-response/#django.http.HttpResponse) のドキュメントに書かれているように、HTTP ステータスコードをコンストラクタに渡して、[`HttpResponse`](/ja/2.2/ref/request-response/#django.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`](/ja/2.2/ref/request-response/#django.http.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`](/ja/2.2/ref/settings/#std-setting-DEBUG) が `False` にセットされているとき、このテンプレートが使われます。

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

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

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

[`page_not_found()`](/ja/2.2/ref/views/#django.views.defaults.page_not_found) ビューは [`handler404`](/ja/2.2/ref/urls/#django.conf.urls.handler404) でオーバーライドされます:

```
handler404 = 'mysite.views.my_custom_page_not_found_view'
```

[`server_error()`](/ja/2.2/ref/views/#django.views.defaults.server_error) ビューは [`handler500`](/ja/2.2/ref/urls/#django.conf.urls.handler500) でオーバーライドされます:

```
handler500 = 'mysite.views.my_custom_error_view'
```

[`permission_denied()`](/ja/2.2/ref/views/#django.views.defaults.permission_denied) ビューは [`handler403`](/ja/2.2/ref/urls/#django.conf.urls.handler403) でオーバーライドされます:

```
handler403 = 'mysite.views.my_custom_permission_denied_view'
```

[`bad_request()`](/ja/2.2/ref/views/#django.views.defaults.bad_request) ビューは [`handler400`](/ja/2.2/ref/urls/#django.conf.urls.handler400) でオーバーライドされます:

```
handler400 = 'mysite.views.my_custom_bad_request_view'
```

> **See also**
>
> CSRF エラービューをオーバーライドするには、[`CSRF_FAILURE_VIEW`](/ja/2.2/ref/settings/#std-setting-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)
```
