業務改善 web開発 programming 旅行系記事多め。

【DjangoのListView】複数のモデルを一つのテンプレートビューに表示する

djangoDjango

今回このような簡易的なTodoリストを作成してみました。
(今後それぞれのデータ右横には「削除」ボタン「Done」ボタン、項目ごとにデータ「追加」ボタンを設定したりといろいろいじっていく予定です)

ディレクトリ構成はこのようになっています。(一部省略)

todo_django
├── config
│   ├── __init__.py
│   ├── __pycache__
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── db.sqlite3
├── lists
│   ├── __init__.py
│   ├── __pycache__
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   │   ├── 0001_initial.py
│   │   ├── __init__.py
│   │   └── __pycache__
│   ├── models.py
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── manage.py
├── static
│   ├── css
│   ├── images
│   └── js
└── templates
    ├── base.html
    └── lists
        └── index.html

「lists」アプリケーションを作成し、その中のmodels.pyに「daily(Todayの箇所で、その日のやることリスト)」「reminder(忘れないようにしておくことリスト)」「objective(直近の目標などを気軽に書くリスト)」の3つのモデル(テーブル)定義を記載しています。

モデルが複数あるためアプリケーションもそれに合わせて分けた方がいいかなとも思いましたが、作業が煩雑になる気もしたので一つのアプリケーション「lists」にまとめました。

通常、モデルからデータを取得してテンプレートに反映する場合はこのような例文を見ることが多いかもしれません。

lists/views.py

from django.shortcuts import render

# ここでモデルのインポートをする。
from .model import daily

def index(request):
    # dailyモデルのオブジェクトを全件取得する
    dailyModel = {'daily_list': daily.objects.all()}

    return render(request, 'lists/index.html', dailyModel)

これであればまずdailyモデルのデータはtemplateに反映することができます。しかし、同時にreminderやobjectiveモデルのデータを反映することはできません。

そこで以下のような書き方であれば、複数モデルを一つのテンプレートでまとめて反映することができます。

参考サイト

lists/views.py

from django.shortcuts import render

from .models import daily, reminder, objective
from django.views.generic import ListView

class IndexView(ListView):
    template_name = 'lists/index.html'
    context_object_name = 'daily_list'
    model = daily

    def get_context_data(self, **kwargs):
        context = super(IndexView, self).get_context_data(**kwargs)
        context.update({
            'reminder_list': reminder.objects.all(),
            'objective_list': objective.objects.all(),
        })
        return context

    def get_queryset(self):
        return daily.objects.all()


index = IndexView.as_view()

ファイル上部に「from django.views.generic import ListView」を追加しクラスベースで記載していきます。また「context.update」の中で2つ目移行のモデルを追加していくことで、複数モデルを表示できるようになります。

templates/lists/index.html

{% block content %}
<div class="container">
    <div class="daily">
        <h2 class="title">Today</h2>
        <ul id="daily-content">
            {% for daily in daily_list %}
                <li>{{ daily.content }}</li>
            {% endfor %}
        </ul>
    </div>
    <div class="done">
        <h2 class="title">Today's done</h2>
    </div>
    <div class="reminder">
        <h2 class="title">Reminder</h2>
        <ul id="reminder-content">
            {% for reminder in reminder_list %}
                <li>{{ reminder.content }}</li>
            {% endfor %}
        </ul>
    </div>
    <div class="objective">
        <h2 class="title">Objective</h2>
        <ul id="objective-content">
            {% for objective in objective_list %}
                <li>{{ objective.content }}</li>
            {% endfor %}
        </ul>
    </div>

</div>
{% endblock %}

「{{ daily.content }}」のcontentは取得したい値のフィールド名です。これはモデルに合わせて内容を変更してください。

コメント

  1. KenChan より:

    Djangoに取り組み始めて3か月。単一モデルのリスト表示はできたのですが、「複数モデル→複数リスト表示」のやりかたを探していました。本記事はドンピシャリでした。ありがとうございました。

タイトルとURLをコピーしました