本文へスキップ
BecomeCoder

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

詳細ページ ― 動的URL と get_object_or_404

ブラウザで完結

導入

一覧の各記事をクリックしたら、その記事だけのページへ。/posts/1//posts/2/…… という動的 URL と、「無ければ 404」を安全に扱う定番を学びます。

説明

<int:pk> で記事の番号を受け取り、get_object_or_404 で「あれば表示、無ければ 404」を1行で書きます。

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", {
                "detail.html": "<h1>{{ post.title }}</h1><p>{{ post.body }}</p>",
            })]},
        }])
    django.setup()

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

class Post(models.Model):
    title = models.CharField(max_length=100)
    body = models.TextField()
    class Meta:
        app_label = "blog"

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

Post.objects.create(title="1本目の記事", body="これは本文です。")
Post.objects.create(title="2本目の記事", body="ふたつめ。")

# 詳細ビュー:pk で1件取得。無ければ自動で404。
def post_detail(request, pk):
    post = get_object_or_404(Post, pk=pk)
    return render(request, "detail.html", {"post": post})

urlpatterns = [path("posts/<int:pk>/", post_detail)]

client = Client()
print("存在する記事:", client.get("/posts/1/").content.decode())
print("存在しない記事のステータス:", client.get("/posts/999/").status_code)  # 404
  • get_object_or_404(Post, pk=pk)主キー pk の記事を取得し、無ければ Http404 を送出(=404 ページ)。Post.objects.get(pk=pk)try/except で囲む定番を、1行にまとめたショートカットです。
  • pk は主キー(primary key)の略で、id と同じもの。Django の慣習でこの名前をよく使います。

一覧(レッスン26)と詳細(このレッスン)がそろえば、あとは一覧の各行に /posts/1/ へのリンクを張るだけで、ブログの読む側は完成です。

やってみよう

client.get("/posts/2/") で2本目の記事を表示したり、/posts/5/ で 404 になることを確かめたりしましょう。記事を増やせば、その番号でアクセスできます。

演習

detail.html を書き換えて、本文の前に「記事番号: N」を表示してください(N は post.id)。出力に 記事番号: 1 が含まれれば成功です。

ヒント1を見る

テンプレートに <p>記事番号: {{ post.id }}</p> を追加します。

ヒント2を見る

post.idpost.pk は同じ値です。

実際に動かしてみよう

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

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

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