Django1.3のClass-based generic viewsを使う

Django1.3で、汎用ビュー(generic views)が関数からクラスベースのものに変更されました。
http://docs.djangoproject.com/en/1.3/ref/class-based-views/
使い方などをメモ。
1.2からのマイグレーションについても、ドキュメントに書かれている。
http://docs.djangoproject.com/en/1.3/topics/generic-views-migration/
以前の関数はまだ使えるけど、duplicated指定になっている。

direct_to_templateの置き換え

ドキュメントの通り単純に、

from django.conf.urls.defaults import patterns, include, url

#from django.views.generic.simple import direct_to_template
from django.views.generic import TemplateView

urlpatterns = patterns('',
    #(r'^$', direct_to_template, {'template': 'index.html'}),  # Django1.2
    (r'^$', TemplateView.as_view(template_name='index.html')),
)

とする。ただし、リクエストメソッドがHEADやPOSTの場合、direct_to_templateの場合はレスポンスを返すが、TemplateViewの場合は405 Method Not Allowedとなる。

TemplateView

TemplateViewはテンプレートを使ってレンダリングしてレスポンスを返すクラス。前述の通りdirect_to_template相当のもの。

# coding: utf-8

from django.views.generic import TemplateView

class MyAppView(TemplateView):
    template_name = 'myapp1/index.html'

    def head(self, request, *args, **kwargs):
        # HEADメソッドの処理...
        return self.get(request, *args, **kwargs)  # bodyを返すべきじゃないとかは置いといてGETと同じ動きをさせてみる

    def post(self, request, *args, **kwargs):
        # POSTメソッドの処理...
        context = self.get_context_data(**kwargs)
        return self.render_to_response(context)

HEADやPOSTメソッドに対応したい場合は、それぞれの小文字名のメソッドを実装する。
レスポンスクラスも差し替え可能(TemplateViewの場合はTemplateResponse)
urls.pyでas_view()を呼んで使う。

from django.conf.urls.defaults import patterns, include, url

from myapp1.views import MyAppView

urlpatterns = patterns('',
    (r'^$', MyAppView.as_view()),
)

ListView/DetailView

指定したモデルのオブジェクト一覧と詳細を提供するビュークラス。object_list, object_detail相当のもの。

from django.views.generic import ListView, DetailView
from myapp1.models import MyModel

class MyModelListView(ListView):
    template_name='list.html'
    model = MyModel

    def get_queryset(self):
        queryset = super(MyModelListView, self).get_queryset()
        # ここでfilterを適用したりする
        return queryset


class MyModelDetailView(DetailView):
    template_name='detail.html'
    model = MyModel

フックポイントが増えているのが嬉しい。
urls.pyのURLパターンの指定で、デフォルトのグループ名が"object_id"から"pk"に変更されたことに注意する。

from django.conf.urls.defaults import patterns, include, url

from myapp1.views import MyModelListView, MyModelDetailView

urlpatterns = patterns('',
    (r'^mymodel/$', MyModelListView.as_view()),
    (r'^mymodel/(?P<pk>\d+)/$', MyModelDetailView.as_view()),
)

CreateView/UpdateView/DeleteView

create_object, update_object, delete_object相当のもの。

from myapp1.forms import MyModelForm

class MyModelCreateView(CreateView):
    model = MyModel
    form_class = MyModelForm  # Formを差し替えられる


class MyModelUpdateView(UpdateView):
    model = MyModel


class MyModelDeleteView(DeleteView):
    model = MyModel
    success_url = '/'  # 処理完了後のリダイレクト先URL

フォームクラスの差し替えは以前の関数のものでも可能だったけど、新たにフォーム生成やバリデーションなどにもフックできるようになっている。
DeleteViewはリクエストメソッドがDELETEでも動作する。
urls.pyの指定はDetailViewなどと同じ。

その他

日付のものもあるけど説明は省略。

まとめ

  • 1.2のgeneric viewから割とすんなり移行できるけど、リクエストメソッドやURLパターンのグループ名など細かな違いがあることに注意する。
  • 以前の関数のものよりもフックポイントがかなり増えたので、generic viewを使える場面は多くなっている。