クラスベースビュー¶
ビューとは、リクエストを受け取り、レスポンスを返す呼び出し可能オブジェクトです。ビューは単なる関数以上のものにもなり得ます。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
If the view is accessed from a GET request, an object list is returned in
the response (using the book_list.html template). But if the client issues
a HEAD request, the response has an empty body and the Last-Modified
header indicates when the most recent book was published. Based on this
information, the client may or may not download the full object list.
非同期のクラスベース・ビュー¶
既に示した同期 (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 の非同期サポートや、非同期ビューの最適な使い方については、 非同期サポート を参照してください。