今回のお題
今回は、djangoのビューを関数ベースからクラスベースに書き換えていきます。
私は今まで関数ベースビューしか書いたことがありませんでしたが、クラスベースに慣れておいた方が便利だという意見をあちこちで目にしたので、良い機会かなと思いました。
目次
- クラスベースビュー・関数ベースビューとは
- クラスベースに変える場合の変更点
- 設定項目が少ない場合の書き方
- 終わりに
クラスベースビュー・関数ベースビューとは
まずは最初に用語の説明をしておきます。
そもそもビューとはリクエストに応じて必要な変数やテンプレートを用意するためのものですが、この必要なものを用意するための処理を関数として表しているものを関数ベースビューと呼びます。
# 関数ベースビュー
def index(request):
books = Book.object.all()
return render(request, "book/index.html", { "books": books }
いつものやつですね。
この書き方は他のフレームワーク(Ruby on RailsやPHP Laravelなど)とほぼ同じなので馴染みがあるという方も多いですし、実際のところ初心者向けの書籍では関数ベースビューから入るものが多いと思います。
ついでに、関数ベースビューに対応したルーティングも載せておきます。
urlpatterns = [
path("index", include(("book.urls", "book"))),
]
urlpatterns = [
path("index", views.index, name="index"),
]
これと同じものをクラスベースビューで書くと以下の通りになります。
from django.views.generic import TemplateView # 他にも色々とimportはありますが省略
class IndexBookView(TemplateView):
template_name = "book.index.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
books = Book.objects.all()
context["books"] = books
return context
urlpatterns = [
path("/index", views.BookIndexView.as_view(), name="index"),
]
とりあえず全体像が掴めたら、変更点を見ていきます。
クラスベースに変える場合の変更点
クラスベースに変える場合の変更点(というか記述するべき項目)は、
- views.pyの中にXxxxviewというクラスを作る(この際にTemplateViewクラスを継承させる)
- そのクラスの中で
template_name
とget_context_data関数
を定義する。 - ルーティングで、ビューの関数ではなくテンプレートビュークラスを呼び出すようにする。
です。
最初のクラスの作成が以下の部分。
class IndexBookView(TemplateView):
TemplateVeiw
クラスを継承しています。
次にtemplate_name
を定義し、呼び出したいテンプレートファイルの相対パスを記述します。
template_name = "book.index.html"
# IndexBookViewが呼ばれた場合には"book/index.html"が表示される。
最後にget_context_data
関数でテンプレートに渡す変数を定義しています。
クラスベースビューではcontextという箱に入って変数が受け渡されるので、そこに必要なものを追加してあげる形ですね。
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
books = Book.objects.all()
context["books"] = books
return context
ちなみに、このget_context_data関数
は親クラス(TemplateViewクラス)にも存在しているので、関数の定義がオーバーライドの形を取ることに注意してください。
これでビューの方は完成なので、ルーティングからテンプレートビューを呼び出せるようにすればOKです。
urlpatters = [
path("index/", views.IndexBookView.as_view(), name="index"),
]
第二引数はviews.テンプレートビュークラス名.as_view()
という形式になります。
設定項目が少ない場合の書き方
クラスベースビューの基本的な書き方は上記の通りで、views.py
で定義したクラスをurls.py
で呼び出すという形になります。
しかし以下のように記述することでviews.py
での処理を省略し、urls.py
への記述のみで完結させることができます。
urlpatterns = [
path("hoge", TemplateView.as_view(
template_name = "hoge.html",
extra_context = { "fuga": "fuga" }
), name="hoge"),
]
要は
- 新しいテンプレートビュークラスを用意せずにデフォルトのTemplateViewをそのまま使う。
-
template_name
とextra_context
をas_view
のキーワード付き引数として渡す(extra_context
はcontextに追加する変数)
ということです。
もちろん変数を用意するロジックとルーティングのロジックは分離させるのが原則なので、あくまでも簡単に書ける場合の処理ですが。
終わりに
以上がクラスベースビューの実装手順でした。
他の言語ではあまり見ない概念ですが、早く慣れていきたいですね。