クラスベース汎用ビューの入門と使い方サンプル(もうすこし詳しく) #1

以前Qiitaに投稿したのですが、Djangoにはクラスベース汎用ビュー(CBV)というのがあります。

いつか書き直したいなぁと思っていたのですが、新しいサイトを立ち上げたのを機にもう一度書いてみます。

Djangoのバージョンも上がりましたしね。



Djangoでいうところのビューとは

ビューというのはMVCで言うところのコントローラーであり、MTVで言うところのビューです。

Djangoを使った人がある人もない人も、何かの開発に関わればMVCという言葉は聞いたことがあると思います。

MVCはざっくり言うと機能や責任の分離であり、その名称を表しています。 モデル・ビュー・コントローラーですね。 ご存知の方も多いと思います。

DjangoではそのことをMTVと呼んでいます。 モデル・テンプレート・ビューです。

DjangoではMVCでいうビューはテンプレートのことですし、MVCでいうコントローラーはビューと言います。

この三つは実際にDjangoの中核を成しています。 私の講座でもモデルを作り、ビューを作り、そしてテンプレートを作ります。 Djangoにおいてビューの作り方は関数ベースのものとクラスベースのものがあります。

関数のビュー

私はクラスベース汎用ビューを推していますが、機能として単純な方がいい場合は関数ベースの方が良いときもあります。 Djangoのビューはリクエストを受け取ってレスポンスを返せばよいだけなので、書き方として関数とクラスのどちらが良いかはありません。

def index(request):
   return HttpResponse('Hello, World!)

このような一般的なPythonの関数でもビューを作ることができます。

requestという引数はリクエストオブジェクトで、アクセスされたページの情報などが入っています。 そして、HttpResponseはレスポンスオブジェクトを返す関数です。 Djangoではこの二つ、引数としてリクエストオブジェクトを受け取る(一般的にはrequestとする)ことと、レスポンスオブジェクトを返すことだけがビューとして動作する条件となっています。

汎用ビューとはなにか

ビューとはコントローラーの事です。

汎用ビューとはその名の通り、一般的なコントローラーのことです。

例えば、普通にウェブサイトを作成すると

  • データを取り出すモデルが違うので指定する必要がある
  • データを供給するテンプレートのデザインが違うのでテンプレートを指定する必要がある

という処理が必要なだけで、内部的なロジックは変わらないことが多いです。

例えば、

  • ブログのトップページは記事の一覧を表示する
  • ページネーションしているので、一度につき10件
  • ブログのトップページ用のデザインがあるので、テンプレートの指定は必要

  • 商品のトップページは商品の一覧を表示する
  • ページネーションしているので、一度につき10件
  • 商品のトップページ用のデザインがあるので、テンプレートの指定は必要

などです。大体同じようなことをしています。

同じようなことをとは

  • 一覧ページはモデルからデータを取得する
  • ページ分割に応じた件数だけ取得する
  • テンプレートを指定する必要がある

といったことです。

これらの処理をはじめから作っておいて、適切なデフォルト値を設定しておこう、 そして、カスタマイズが必要であればデフォルト値を上書きしてもらおう、 というのが汎用ビューの考え方です。

クラスベース汎用ビューとは

上記の汎用ビューの実装がクラスベースになったものです。 要はMixinとして実装している汎用ビューのことを言います。

もちろん、関数ベースでの汎用ビューもあります(ありました)が、いま使っている人は少ないのではないかと思います。

のっけから長かったですが、これが汎用ビューの存在意義です。

クラスベース汎用ビューの使い方

クラスベース汎用ビューは、先ほど書いてあるとおりMixinです。 従って、自分で作成したクラスで継承して組み込みます。

では、サンプルを書いてみたいと思います。

下準備

ここでは、

django-admin createproject foo

のようにして、プロジェクトはすでに作ってあるものとします。

では、アプリケーションを作っていきましょう。

試しに、ブログ記事のようなものを作ってみたいと思います。

django-admin createapp article

これで、article アプリケーションが作成されました。

つぎの、モデルを作成します。

from django.db import models

class Article(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()

簡単にするため、フィールドの数は2つにしました。

マイグレーションなどは割愛することにします。

汎用ビューの使い方

続いてviews.pyにクラスベース汎用ビューを使って一覧ページを作ってみたいと思います。

from django.views.generic import ListView

from .models import Article


class ArticleListView(ListView):
    model = Article

基本的にはこれだけでテンプレートにデータが供給されます。

上から説明すると

from django.views.generic import ListView

クラスベース汎用ビューは django.views.generic に入っていることが多いです。 別のモジュールからインポートする必要があるものもありますが、8割ここに入っています。

次に、

from .models import Article は自分で作ったモデルですね。 どのモデルからデータを取得するのか指定する必要があるのでここでインポートしています。

次の2行がクラスベース汎用ビューの使い方です。

class ArticleListView(ListView): でクラスを定義しています。 もちろん、クラスベース汎用ビューである ListView を継承しています。

ビューの名前はモデル+汎用ビューの名前であることが多いです。

次に、 model = Article となっています。 ここに指定されたモデルからデータを読み込みます。 デフォルトでは全件読み出してくるので注意が必要です。

テンプレートの指定

さて、ここにテンプレートの指定がありません。 クラスベース汎用ビューではテンプレート名がモデルと汎用ビューの種類で決まります。 今は、

モデル → Article、汎用ビュー → ListView

ですので

article_list.html

という名前のテンプレートが指定されています。これはデフォルト値ですので変更することも可能です。 (モデル名)_(汎用ビューの種類).html という名称が自動で選ばれます。

テンプレートのパスですが、実は settings.py の設定に依存しています。

settings.py に自動生成されている TEMPLATE というリストがあります。 要素は辞書になっていて、テンプレートの設定が記述されています。

そこに APP_DIR というキーがあるのですが、この値が True であれば、各アプリケーションの内部の templates というフォルダを探索します。

今回のケースで言えば article/templates フォルダの中身を探索する、という事です。 無ければ探索しないだけでエラーなどにはなりません。

templates を作成しましょう。 Pythonモジュールなどではありませんので、ただのフォルダでOKです。 __init__.pyは必要ありません(あっても問題ありません)。

次が重要です。

クラスベース汎用ビューでは、templatesフォルダの中のモデル名のフォルダを探索します。

つまり、今回の場合、templatesフォルダの中の

article/article_list.html を探します。

ですから、まずはarticleフォルダを作成して、その中にテンプレートファイルを作成してください。

urls.pyの設定

urls.py は実はとても重要です。

DjangoはRailsのようにURLを自動で生成しません。

自分でURLを設定する必要があります。 そして、そのURLとビューを紐つけるのがこのurls.pyです。

アクサスできるURLを指定し、そこにアクセスされたらどのビューが反応するかをここで指定します。

クラスベース汎用ビューであれば、ここに、as_view()というメソッドを指定します。 そうすれば、あとはクラスベース汎用ビューがよしなに処理してくれます。

次に続く

ずいぶんと長くなってしまったので、次回に続きます。


初稿: 2019年10月26日23:55 | 最終編集: 2019年10月27日1:03