ホーム >  Python > Django >  Djangoの汎用ビュー入門(ListView)


Posted:2018/05/22 9:00:36 AM|Category : Django

Djangoの汎用ビュー入門(ListView)

Djangoは、汎用ビューを使って簡易的なコーディングでアプリケーションを作成することができます。

ListView

ListViewは汎用ビューの一つで、一覧ページなどを作る時に使用します。テーブルからデータ一覧を取得して表示するイメージです。

汎用ビューについては、前回の説明を参考にして下さい。

Djangoの汎用ビュー入門(TemplateView)

具体例

ListViewを利用し、Postモデルの一覧を以下のように表示します。

前提

①以下のようなDjangoアプリ構成を作ります。プロジェクト名が「pj1」で、アプリケーション名が「users」です。プロジェクトの設定は済ませたものとします。赤字のファイルは、今回変更する部分です。

  • pj1/
  • pj1/
  • __init__.py
  • settings.py
  • urls.py
  • wsgi.py
  • users/
  • __init__.py
  • admin.py
  • apps.py
  • urls.py
  • views.py
  • models.py
  • templates/
  • index.html
  • post_list.html
  • manage.py

②表示するデータとして、models.pyに以下のモデルを定義します。

from django.contrib.auth.models import User
from django.db import models

class Category(models.Model):
    """カテゴリー"""
 
    name = models.CharField(max_length=255)
 
    def __str__(self):
        return self.name
 
 
class Post(models.Model):
    """ブログのポスト"""
 
    title = models.CharField(max_length=255)
    text = models.TextField()
    category = models.ManyToManyField(Category)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
 
    def __str__(self):
        return self.title

③Postモデル一覧を表示するhtmlテンプレートを用意します。

{% extends "base.html" %}
{% block content %}
<div class="container-fluid" style="margin-top: 60px;">
  <div class="row">
    <div class="col-md-6 offset-md-3" >
      <div class="card">
        <div class="card-header">記事一覧</div>
	  {% for post in post_list %}
          <div class="card-body p-3">
            <p class="card-text">
	      タイトル:{{ post.title }} 
	      日付:{{ post.created_at }}
	    </p>
            <a href="{% url 'users:detail' post.pk %}" class="card-link">続きを読む</a>
         </div><!-- end card-body -->
	 {% endfor %}
      </div><!-- end card -->
    </div><!-- end col-md-6 offset-md-3 -->
  </div><!-- end row -->
</div><!-- end container-fluid -->
{% endblock %}

ListView使い方

汎用ビューは主にviews.pyで使用されます。また、そのViewをurls.pyでas_view()という関数でURLを紐つけます。Djangoプロジェクト内に「user」というアプリケーションを作成したとします。

from django.views.generic import ListView
from foo.model import Post, Category

class PostView(generic.ListView):
    model = Post
    template_name = 'post_list.html'

「model = Post」はリストを作成するモデルです。

from foo.views import SampleTemplateView

urlpatterns = [
    url(r'^sample$', PostView.as_view()),
]

「/sample」にアクセス際にPostViewが処理を行います。

<ul>
  {% for item in object_list %}
  <li>{{ item }}</li>
  {% endfor %}
</ul>

テンプレートでは、上記のように記述します。

モデル指定方法

class PostView(generic.ListView):
    model = Post

上記のようにモデル(テーブル)を指定します。「model = Post」とすることで、今回の例だと「Post.objects.all()」を裏側で行ってくれます。

class PostView(generic.ListView):
    queryset = Post.objects.all()

上記のように指定してもOKです。

class PostView(generic.ListView):
    def get_queryset(self):
        return Post.objects.all()

又は上記のよにします。

分割取得

from django.views.generic import ListView
from foo.model import Post

class PostView(ListView):
    model = Post
    paginate_by = 5

ListViewはデフォルトで全件取得します。全件ではなく、分割で一覧を取得する場合は、「paginate_by」という変数に数値を入力します。5件ずつ分割したいのなら、上記のように記述します。

フィルタリング

class PostView(ListView):
    model = Post
    paginate_by = 5

    def get_queryset(self):
        return Post.objects.filter(some_column=foo)

取得するデータのソート順を変えたり、フィルタリングして制御したい場合があります。その時は、「get_queryset」メソッドをオーバーライドします。「get_queryset」で定義されたクエリを発行し、データをobject_listに格納します。

class PostView(ListView):
    model = Post
    paginate_by = 5
    queryset = Post.objects.filter(some_column=foo)

上記のように「get_queryset」メソッドを省略することも可能です。どちらを使っても結果は変わりません。

動的にクエリを発行したいのなら「get_queryset」メソッドをオーバーライドし、常に同じ結果を求めるのならオーバライドなしを使えば良いと思います。

別のモデル取得

class PostView(ListView):
    model = Post
    paginate_by = 5

    def get_queryset(self):
        return Post.objects.filter(some_column=foo)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**data)
        context["bar"] = OtherModel.objects.all()  # 他のモデルからデータを取得
        return context

「get_context_data」メソッドをオーバーライドすれば、他のテーブル(ここではOtherModel)からのデータをテンプレートに渡すことができます。ただし、このOtherModelは汎用ビューの制御下にはありません。context[“bar”]にはOtherModelの全件数が格納されます。

テンプレート指定方法

class PostView(ListView):
    model = Post
    template_name = 'mymodel.html'

上記のようにすると、どのテンプレートを使うか指定できます。

class PostView(ListView):

    model = Post

実は、テンプレートは指定しなくてもOKです。

<app name>/<model name>_list.html

なくてもよいということは、デフォルト値があります。デフォルト値は上記のようになります。(今回の例だとusers/post_list.htmlになります。)

context_object_name

class PostView(generic.ListView):
    model = Post
    context_object_name = 'all_post'

上記のような指定もあります。これは、データベースから取り出した一覧データを、templateに渡す際の名前です。

<model name>_list

context_objetc_nameが空だったならば、上記のような名前になります。今回だとpost_listです。「object_list」という名前でもアクセス可能なので、面倒な場合はこちらにしてもよいでしょう。

まとめ

ListViewで頻繁に使う記述は以下のとおりです。

queryset リストで表示したいデータ(配列)を入れます。
context_object_name querysetの名前を指定します。(指定しなければ「modelName_list」という名前がデフォルトです)。

トラックバック用のURL
プロフィール

名前:イワサキ ユウタ 職業:システムエンジニア、ウェブマスター、フロントエンドエンジニア 誕生:1986年生まれ 出身:静岡県 特技:ウッドベース 略歴 20

最近の投稿
人気記事
カテゴリー
広告