クラスベースビュー

ビューとは、リクエストを受け取りレスポンスを返す、呼び出し可能なオブジェクトです。Djangoは、関数だけでなく、クラスを使ったビューの例もいくつか用意しています。これらのクラスは、ビューを構造化し、継承とミックスインを利用してコードを再利用することを可能にします。この後見ることになる、単純なタスクのための汎用ビューもいくつかありますが、各自のユースケースに合った、再利用可能なビューの構造を設計したいかもしれませんね。完全な詳細に関しては class-based views reference documentation を参照してください。

基本的な例

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() に渡されたすべての引数は、クラスで設定された属性を上書きします。次の例では TemplateViewtemplate_name を設定しています。同様の上書きのパターンは、RedirectViewurl 属性でも使えます。

ジェネリックビューのサブクラス化

次に、ジェネリックビューのもっと強力な使用例として、既存のビューを継承して、新しい値やメソッドを提供するために、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()),
]

組み込みのジェネリックビューの使用方法の詳細については、次のトピック generic class-based views を参照してください。

その他の 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
        response['Last-Modified'] = last_book.publication_date.strftime('%a, %d %b %Y %H:%M:%S GMT')
        return response

ビューが GET リクエストでアクセスされた場合、レスポンスでは (book_list.html テンプレートを使用して) シンプルなプレインテキストのオブジェクトリストが返されます。しかし、クライアントが HEAD リクエストを発行した場合には、レスポンスの body は空にし、Last-Modified ヘッダに本が最後に出版された時刻を設定して返します。この情報を使うことで、クライアントはオブジェクトのリスト全体をダウンロードするかどうかを判断できるようになります。

Back to Top