本文へスキップ
BecomeCoder

Djangoコース · 第6章 アプリを組み立てる · レッスン26

一覧ページ ― モデル×ビュー×テンプレート

ブラウザで完結

導入

ブログのトップに、記事の一覧を出しましょう。「モデルからデータを取り、テンプレートに流し込んでレスポンスにする」という、Django の王道の流れを1つにまとめます。

説明

第1章で見た MTV の流れが、そのままコードになります。

flowchart LR
  R["GET /"] --> V["ビュー post_list<br/>Post.objects.all()"]
  V --> M[("モデル Post")]
  V --> T["テンプレート<br/>{% for post in posts %}"]
  T --> RES["HTML レスポンス"]
import django
from django.conf import settings
if not settings.configured:
    settings.configure(DEBUG=True, SECRET_KEY="dev",
        ROOT_URLCONF=__name__, ALLOWED_HOSTS=["testserver"],
        INSTALLED_APPS=[],
        DATABASES={"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": ":memory:"}},
        TEMPLATES=[{
            "BACKEND": "django.template.backends.django.DjangoTemplates",
            "OPTIONS": {"loaders": [("django.template.loaders.locmem.Loader", {
                "list.html": (
                    "<h1>ブログ記事一覧</h1><ul>"
                    "{% for post in posts %}<li>{{ post.title }}({{ post.views }}回)</li>{% endfor %}"
                    "</ul><p>全{{ posts.count }}件</p>"
                ),
            })]},
        }])
    django.setup()

from django.db import models, connection
from django.shortcuts import render
from django.urls import path
from django.test import Client

class Post(models.Model):
    title = models.CharField(max_length=100)
    views = models.IntegerField(default=0)
    class Meta:
        app_label = "blog"

with connection.schema_editor() as schema:
    schema.create_model(Post)

Post.objects.create(title="Djangoを始めよう", views=120)
Post.objects.create(title="テンプレート入門", views=80)
Post.objects.create(title="モデルの基礎", views=200)

# ビュー:モデルから取り出し、テンプレートに渡す
def post_list(request):
    posts = Post.objects.order_by("-views")   # 人気順
    return render(request, "list.html", {"posts": posts})

urlpatterns = [path("", post_list)]

client = Client()
print(client.get("/").content.decode())
  • ビューは Post.objects.order_by("-views") で記事を取り、render(request, "list.html", {"posts": posts}) でテンプレートに渡します。
  • テンプレートは {% for post in posts %} で1件ずつ回し、{{ post.title }} のようにモデルのフィールドにそのままアクセスできます。
  • {{ posts.count }} のように、テンプレート内から QuerySet のメソッドも呼べます。

これが Django の一番よく書く形です。あとは URL とテンプレートを増やしていけば、ページが増えていきます。

やってみよう

order_by("-views")order_by("title") に変えて並び順を変えたり、Post.objects.create(...) で記事を足したりして、一覧の表示が変わることを確かめましょう。

演習

post_list を改造して、views が 100 以上の記事だけを一覧に出してください(人気記事一覧)。filter を使います。出力に テンプレート入門(80回)が含まれないようにできれば成功です。

ヒント1を見る

posts = Post.objects.filter(views__gte=100).order_by("-views")

ヒント2を見る

テンプレートは変更不要です。ビューの取得条件だけを変えます。

実際に動かしてみよう

本文のサンプルや演習のコードは、コードブロック右上の「コピー」ボタンでコピーして、下のエディタに貼り付ければそのまま実行できます。

Python — ライブラリ付きで実行(Pyodide)

numpy / pandas / matplotlib が使える本物のPython(Pyodide)を読み込みます。初回のみ読み込みに少し時間がかかります(以降はブラウザにキャッシュされます)。
スクロールして表示された時点でも自動で読み込まれます。