1-12. ListViewを使ったリスト表示画面の作成

今回のテーマは「ListViewを使った一覧表示画面の作成」です。クラスベースビューとしては現在までにTemplateViewを見ていきましたが、おそらくその次に初心者の方が使いやすいのがListViewとDetailViewだと思います。ListViewはリスト表示、DetailViewは詳細表示を作成するのに向いているクラスベースビューです。名前の通りですね。

※本ページはListViewを使ったリスト表示画面の作成まで読まれた方を対象としています。そのためサンプルソースコードが省略されている場合があります。


準備

今回はトピックの一覧表示をするので管理画面からトピックに関するダミーデータを挿入しましょう。管理画面のTOPIC画面から「TOPICを追加」を押します。

項目を入力していきます。入力したら保存を押せばトピックが出来上がります。一覧表示の練習なので4つぐらい登録しておきましょう。

トピック一覧表示の作成

今回はbaseアプリケーションに作成したトップページに新着トピックをリスト表示するページを作成します。theadアプリケーションのモデルをbaseアプリケーションで使うのが気になる方はthread/views.pyでビューを作成してbase/urls.pyもしくはmysite/urls.pyでビューを呼び出してもいいと思います。筆者はトップページなどのbaseアプリケーションはモデルを持たず、他のアプリケーションからインポートして使うことが多いですが、好みの問題かと思います。 まずはテンプレートを以下のように修正します。

templates/base/top.html

{% extends 'base/base.html' %}
{% block title %}ITについて切磋琢磨する掲示板 - {{ block.super }}{% endblock %}
{% block content %}
<div class="ui grid stackable">
  <div class="eleven wide column">
    <div class="ui breadcrumb">
      <a class="section">TOP</a>
      <i class="right angle icon divider"></i>
      <a class="section">category</a>
      <i class="right angle icon divider"></i>
      <div class="active section">thread</div>
    </div>
    <div class="ui segment">
      <div class="content">
        <div class="header"><h3>新着スレッド</h3></div>
        <div class="ui divided items">
          {% for topic in topic_list %}
          <div class="item">
            <div class="content">
              <div class="header">
                <a><h4>{{topic.title}}</h4></a>
              </div>
              <div class="meta">
                <span class="name">{{topic.user_name}}</span>
                <span class="date">{{topic.created}}</span>
              </div>
            </div>
          </div>
          {% endfor %}
        </div>
      </div>
    </div>
  </div>
  {% include 'base/sidebar.html' %}
</div>
{% endblock %}

次にbase/views.pyにTopicListViewを追加して修正します。

base/views.py

from django.shortcuts import render
from django.views.generic import TemplateView, ListView
# from django.http import HttpResponse
# from django.template import loader
from thread.models import Topic

def top(request):
    """TOP画面表示用関数

    関数ベースのビューの説明として作成

    """
#    template = loader.get_template('base/top.html')
    ctx = {'title': 'Django学習ちゃんねる(仮)'}
#    return HttpResponse(template.render(ctx, request))
    return render(request, 'base/top.html', ctx)

class TopView(TemplateView):
    """TOP画面表示用クラス

    クラスベースのビューの説明として作成

    """
    template_name = 'base/top.html'

    def get_context_data(self, **kwargs):
        ctx = super().get_context_data(**kwargs)
        ctx['title'] = 'IT学習ちゃんねる(仮)'
        return ctx

#今回追加したクラス
class TopicListView(ListView):
    """TOP画面表示クラス

    リストビューの説明として作成

    """
    template_name = 'base/top.html'
    model = Topic
    context_object_name = 'topic_list'

base/urls.pyも変更しましょう。

base/urls.py(一部抜粋)

  urlpatterns = [
-     path('', views.TopView.as_view(), name='top'),
+     path('', views.TopicListView.as_view(), name='top'),
      path('terms/', TemplateView.as_view(template_name='base/terms.html'), name='terms'),
  ]

これで一覧表示されました。簡単ですね。ちなみにcontext_object_name=’topic_list’としましたが、これがなくても問題なく表示されます。理由はListViewを使用したときのコンテキストで渡すデフォルトの名前が"モデル名_list"だからです。今回はデフォルトでtopic_listが渡されています。ただ、この暗黙の命名はDjangoに馴染みのないエンジニアに混乱をもたらしますのでテンプレート側に何を渡しているのかcontext_object_nameで明確に宣言したほうが良いと思います。 さて、この新着スレッドですが、作成日で降順に並べるように変更しましょう。非常に簡単に出来ます。base/views.pyを少し変更するだけです。

base/views.py(一部抜粋)

  class TopicListView(ListView):
      template_name = 'base/top.html'
-     model = Topic
+     queryset = Topic.objects.order_by('-created')
      context_object_name = 'topic_list'

modelの変わりにquerysetを使用します。ListViewはmodelもしくはquerysetが必須です。get_queryset関数をオーバライドしても良いです。Topic.objectにはBaseManageを継承したクラスであり、一般的にDjangoのデータベースCRUD処理はこのobjectを通して行うことが出来ます。今回はorder_by()関数を用いて作成日の降順に並べました。’created’にマイナス(-)がつくことで降順を表現しています。慣れない内はちょっとギョッと・・しません? ブラウザで確認するとこのような画面が見えると思います。

最後に

モデルに働きかけViewがユーザーに見せるべきデータを揃え、テンプレートに渡すというDjangoのMVT全ての役者が揃いましたね。次回はDetailViewを使用して表示処理を行っていきます。

Sponsored Link


コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です