クラスベースビュー¶
ビューとは、リクエストを受け取り、レスポンスを返す呼び出し可能オブジェクトです。ビューは単なる関数以上のものにもなり得ます。Django ではビューとして使用できるいくつかのクラスを提供しており、これらを利用することで、ビューを構造化し、継承やミックスインを活用してコードを再利用できます。また、汎用ビュー(generic view)も用意されていますが、それについては後ほど説明します。あなたのユースケースに合った再利用可能なビューの構造を設計することもできます。詳細については、クラスベースビューのリファレンスドキュメント を参照してください。
基本的な例¶
Django は、さまざまなアプリケーションに広く適用できるベースビュークラスを用意しています。 View
クラスを継承したすべてのビューは、指定した URL へのビューのリンクや、送り出す HTTP メソッド、その他よく使われる機能をハンドリングします。 RedirectView
は HTTP リダイレクトを行うビュークラス、 TemplateView
はベースビューを拡張してテンプレートレンダリングの機能をもたせたビュークラスです。
URLconfでの使用法¶
ジェネリックビューを使用する最もダイレクトな方法は、URLconf 内で直接オブジェクトを作成することです。クラスベースビューの属性をいくつか変更するだけなら、 as_view()
のメソッド呼び出しに渡せばよいのです。
from django.urls import path
from django.views.generic import TemplateView
urlpatterns = [
path("about/", TemplateView.as_view(template_name="about.html")),
]
as_view()
に渡されたすべての引数は、クラスで設定された属性を上書きします。次の例では TemplateView
の template_name
を設定しています。同様の上書きのパターンは、RedirectView
の url
属性でも使えます。
ジェネリックビューのサブクラス化¶
次に、ジェネリックビューのもっと強力な使用例として、既存のビューを継承して、新しい値やメソッドを提供するために、 template_name
などの属性や get_context_data
などのメソッドをサブクラスで上書きする方法を紹介します。たとえば、1つのテンプレート about.html
だけを表示するビューを作ることを考えてみてください。Django には、このために利用できるジェネリックビュー TemplateView
があるので、これをサブクラス化し、テンプレート名を上書きすることで実装できます。
# some_app/views.py
from django.views.generic import TemplateView
class AboutView(TemplateView):
template_name = "about.html"
あとは、URLconf にこの新しいビューを追加する必要があります。 TemplateView
は1つのクラスであって、関数ではありません。そのため、指定する URL に対して、代わりに as_view()
クラスメソッドを設定しています。これによって、クラスベースビューに対する関数ライクな要素を指定できます。
# urls.py
from django.urls import path
from some_app.views import AboutView
urlpatterns = [
path("about/", AboutView.as_view()),
]
組み込みの汎用ビューの使用方法の詳細については、次のトピック 汎用のクラスベースビュー を参照してください。
その他の HTTP メソッドをサポートする¶
誰かが私たちのライブラリに HTTP 経由でアクセスして、ビューを API として使用したいという状況を考えてください。API クライアントはたびたびコネクションを張り、最終訪問日時以降に出版された本のデータをダウンロードするとします。しかし、新しい本の情報が存在しない場合には、データベースから本のデータを取得し、レスポンステキストをレンダリングし、クライアントに送信し返すための CPU タイムとバンド幅は無駄になってしまいます。最新の本が出版された時点で API に問い合わせた方が好ましいかもしれません。
そのために、URLconf 内で、本のリストビューへの URL を次のようにマッピングします。
from django.urls import path
from books.views import BookListView
urlpatterns = [
path("books/", BookListView.as_view()),
]
そして、ビューには次のように書きます。
from django.http import HttpResponse
from django.views.generic import ListView
from books.models import Book
class BookListView(ListView):
model = Book
def head(self, *args, **kwargs):
last_book = self.get_queryset().latest("publication_date")
response = HttpResponse(
# RFC 1123 date format.
headers={
"Last-Modified": last_book.publication_date.strftime(
"%a, %d %b %Y %H:%M:%S GMT"
)
},
)
return response
ビューが GET
リクエストからアクセスされた場合、レスポンスにはオブジェクトリストが返されます( book_list.html
テンプレートを使用しています)。しかし、クライアントがHEADリクエストを発行した場合、レスポンスは空のボディを持ち、 Last-Modified
ヘッダーは最新の書籍がいつ発行されたかを示します。この情報に基づいて、クライアントは完全なオブジェクトリストをダウンロードするかどうかを判断します。
非同期のクラスベース・ビュー¶
既に示した同期 (def
) メソッドハンドラと同様に、 View
サブクラスは await
: を使用して非同期 (async def
) メソッドハンドラを定義できます:
import asyncio
from django.http import HttpResponse
from django.views import View
class AsyncView(View):
async def get(self, request, *args, **kwargs):
# Perform io-blocking view logic using await, sleep for example.
await asyncio.sleep(1)
return HttpResponse("Hello async world!")
1つのビュークラス内では、すべてのユーザー定義メソッドハンドラは def
を使用した同期的なものか、 async def
を使用した非同期的なものでなければなりません。 def
と async def
が混在している場合、 as_view()
で ImproperlyConfigured
例外が発生します。
Django は自動的に非同期ビューを検出し、非同期コンテキストで実行します。Django の非同期サポートや、非同期ビューの最適な使い方については、 非同期サポート を参照してください。