0
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

djangoのビューを関数ベースからクラスベースに書き換える

Posted at

今回のお題

今回は、djangoのビューを関数ベースからクラスベースに書き換えていきます。

私は今まで関数ベースビューしか書いたことがありませんでしたが、クラスベースに慣れておいた方が便利だという意見をあちこちで目にしたので、良い機会かなと思いました。

目次

  • クラスベースビュー・関数ベースビューとは
  • クラスベースに変える場合の変更点
  • 設定項目が少ない場合の書き方
  • 終わりに

クラスベースビュー・関数ベースビューとは

まずは最初に用語の説明をしておきます。

そもそもビューとはリクエストに応じて必要な変数やテンプレートを用意するためのものですが、この必要なものを用意するための処理を関数として表しているものを関数ベースビューと呼びます。

views.py
# 関数ベースビュー
def index(request):
  books = Book.object.all()
  return render(request, "book/index.html", { "books": books }

いつものやつですね。

この書き方は他のフレームワーク(Ruby on RailsやPHP Laravelなど)とほぼ同じなので馴染みがあるという方も多いですし、実際のところ初心者向けの書籍では関数ベースビューから入るものが多いと思います。

ついでに、関数ベースビューに対応したルーティングも載せておきます。

project/urls.py(プロジェクト側)
urlpatterns = [
  path("index", include(("book.urls", "book"))),
]
book/urls.py(アプリ側)
urlpatterns = [
  path("index", views.index, name="index"),
]

これと同じものをクラスベースビューで書くと以下の通りになります。

views.py
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
book/urls.py
urlpatterns = [
  path("/index", views.BookIndexView.as_view(), name="index"),
]

とりあえず全体像が掴めたら、変更点を見ていきます。

クラスベースに変える場合の変更点

クラスベースに変える場合の変更点(というか記述するべき項目)は、

  • views.pyの中にXxxxviewというクラスを作る(この際にTemplateViewクラスを継承させる)
  • そのクラスの中でtemplate_nameget_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_nameextra_contextas_viewのキーワード付き引数として渡す(extra_contextはcontextに追加する変数)

ということです。

もちろん変数を用意するロジックとルーティングのロジックは分離させるのが原則なので、あくまでも簡単に書ける場合の処理ですが。

終わりに

以上がクラスベースビューの実装手順でした。

他の言語ではあまり見ない概念ですが、早く慣れていきたいですね。

0
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?