ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
| この記事の要点 |
|
なぜ直書きしないのか
<!-- 直書き。URL 設計を変えると全テンプレートを直すことになる -->
<a href="/blog/2026/09/07/">記事</a>
<!-- 名前で参照。urls.py を変えても自動で追従する -->
<a href="{% url 'blog:detail' pk=article.pk %}">記事</a>
直書きは、サブディレクトリ配下に配置したときにも壊れます。{% url %} なら FORCE_SCRIPT_NAME やプレフィックスの変更にも追従します。
urls.py に名前を付ける
# config/urls.py
from django.urls import include, path
urlpatterns = [
path("blog/", include("blog.urls")),
]
# blog/urls.py
from django.urls import path
from . import views
app_name = "blog" # 名前空間
urlpatterns = [
path("", views.index, name="index"),
path("<int:pk>/", views.detail, name="detail"),
path("<int:year>/<int:month>/", views.archive, name="archive"),
path("tag/<slug:slug>/", views.tag, name="tag"),
]
テンプレートから参照する
<a href="{% url 'blog:index' %}">一覧</a>
<!-- 位置引数 -->
<a href="{% url 'blog:detail' article.pk %}">{{ article.title }}</a>
<!-- キーワード引数(読みやすい) -->
<a href="{% url 'blog:archive' year=2026 month=9 %}">2026年9月</a>
<!-- 変数に入れて使い回す -->
{% url 'blog:detail' article.pk as detail_url %}
<a href="{{ detail_url }}">詳細</a>
<a href="{{ detail_url }}#comments">コメント</a>
ビュー名は必ずクォートで囲みます。囲まないと変数として解釈され、NoReverseMatch になります。
クエリ文字列とフラグメント
<!-- {% url %} の中に ?page=2 は書けない。外に付ける -->
<a href="{% url 'blog:index' %}?page=2&sort=new">次のページ</a>
<!-- ページャーで現在の条件を保ちたいとき -->
<a href="?page={{ page_obj.next_page_number }}">次へ</a>
<!-- アンカー -->
<a href="{% url 'blog:detail' article.pk %}#comment-{{ comment.id }}">該当コメント</a>
HTML の属性値では & をエスケープして & と書くのが正式です。ブラウザは & のままでも解釈しますが、バリデータでは警告になります。
リンクの種類ごとの書き方
| 用途 | 書き方 |
|---|---|
| サイト内のページ | {% url 'blog:detail' pk %} |
| CSS / JS / 画像 | {% static 'css/style.css' %} |
| アップロードされたファイル | {{ article.image.url }} |
| モデルの詳細ページ | {{ article.get_absolute_url }} |
| 外部サイト | URL を直書き + rel="noopener" |
| メール | mailto: + アドレス |
{% load static %}
<link rel="stylesheet" href="{% static 'css/style.css' %}">
<img src="{{ article.image.url }}" alt="{{ article.title }}">
<a href="https://example.com/" target="_blank" rel="noopener noreferrer">外部</a>
{% static %} を使うには、そのテンプレートの先頭で {% load static %} が必要です。読み込みの詳細は 静的ファイルの読み込み を参照してください。
モデル側に URL を持たせる
from django.db import models
from django.urls import reverse
class Article(models.Model):
title = models.CharField(max_length=200)
def get_absolute_url(self):
return reverse("blog:detail", kwargs={"pk": self.pk})
<a href="{{ article.get_absolute_url }}">{{ article.title }}</a>
定義しておくと、CreateView や UpdateView の保存後の遷移先としても自動的に使われ、管理画面にも「サイト上で表示」ボタンが出ます。テンプレートではかっこを書かない点に注意してください。
Python 側で URL を作る
from django.shortcuts import redirect
from django.urls import reverse
url = reverse("blog:detail", kwargs={"pk": 1}) # '/blog/1/'
return redirect("blog:detail", pk=1) # 名前をそのまま渡せる
# メールなどに載せる完全な URL
full = request.build_absolute_uri(url) # 'https://example.com/blog/1/'
NoReverseMatch の直し方
NoReverseMatch: Reverse for 'detail' not found.
'detail' is not a valid view function or pattern name.
| 原因 | 確認するところ |
|---|---|
name= を付けていない | urls.py の path() |
| 名前空間を書き忘れ | app_name があるなら 'blog:detail' と書く |
| 引数の数が合わない | <int:pk> があるのに引数なしで呼んでいないか |
| 型が合わない | <int:pk> に文字列やスラッグを渡していないか |
| ビュー名をクォートしていない | {% url blog:detail %} は不可 |
include() していない | ルートの urls.py に登録されているか |
# 登録されている URL 名を一覧する
python manage.py shell -c "from django.urls import get_resolver; print(sorted(get_resolver().reverse_dict.keys()))"
一覧から詳細へリンクする
<ul>
{% for article in articles %}
<li>
<a href="{% url 'blog:detail' article.pk %}">{{ article.title }}</a>
<span>{{ article.created_at|date:"Y年n月j日" }}</span>
</li>
{% empty %}
<li>記事がありません</li>
{% endfor %}
</ul>
{% empty %} はループする対象が空だったときに使われます。{% if articles %} で囲む必要がありません。
いま開いているページを強調する
<nav>
<a href="{% url 'blog:index' %}"
class="{% if request.resolver_match.url_name == 'index' %}active{% endif %}">
一覧
</a>
</nav>
request.resolver_match には、いま処理されているルートの情報(url_name / app_name / kwargs)が入っています。パス文字列を比較するより壊れにくい方法です。
request をテンプレートで使うには、settings.py の TEMPLATES の context_processors に django.template.context_processors.request が入っている必要があります(既定で入っています)。
ページ送りのリンク
{% if page_obj.has_previous %}
<a href="?page={{ page_obj.previous_page_number }}">前へ</a>
{% endif %}
<span>{{ page_obj.number }} / {{ page_obj.paginator.num_pages }}</span>
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}">次へ</a>
{% endif %}
?page=2 だけを書くと現在の他の検索条件が消えます。条件を保ちたい場合は、ビュー側で組み立てた文字列を渡すのが確実です。
def index(request):
params = request.GET.copy()
params.pop("page", None)
return render(request, "blog/index.html", {
"page_obj": page_obj,
"query_string": params.urlencode(), # 'q=Python&sort=new'
})
<a href="?page={{ page_obj.next_page_number }}&{{ query_string }}">次へ</a>
安全面の注意
- ユーザーが入力した URL をそのまま
hrefに出さない —javascript:で始まる値を入れられる。http/httpsだけを許可する target="_blank"にはrel="noopener noreferrer"を付ける- Django のテンプレートは既定でエスケープされる。
|safeや{% autoescape off %}を安易に使わない - ログイン後の遷移先を
?next=で受け取るときは、外部ドメインでないことを検証する(ビューでリダイレクト)
関連
- テンプレート(Template) — 親カテゴリ
- URLディスパッチャー(ルーティング処理)
- ルーティングの作成
- 静的ファイルの読み込み
- viewからtemplateへの遷移方法
- ビューでリダイレクト
ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
子ページはありません
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript で base URL を取得する方法|window.location.origin
- 4 YouTube Data API v3 エラー一覧|403・400・404 の原因と対処
- 5 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 6 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 7 Spring Frameworkのアノテーション一覧
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- 【django】ログイン 認証機能 2026-09-08 03:22:09
- MySQL ERROR 1063 Incorrect column specifier for column|原因と直し方 2026-09-08 03:11:09
- 【PHPエラー】Object of class stdClass could not be converted to string 2026-09-07 07:46:04
- Julia Genie ローカル開発サーバ起動完全ガイド 2026-09-07 07:46:04
- Wi-Fi とは|規格と世代(Wi-Fi 4〜7)・周波数帯・CSMA/CA・WPA3 NEW 2026-09-07 07:45:13
- set コマンドでシェルオプションと位置パラメータを操作 | bash 2026-09-07 07:45:13
- JPEG(.jpg/.jpeg)画像形式の完全ガイド — 仕様・マジックナンバー・他形式との比較・EXIF 2026-09-07 07:45:13
- UE5 Get Overlapping Actorsで特定クラスだけ処理|Class Filter・Cast To 2026-09-07 07:45:13
- Linuxで特定拡張子のファイルを再帰削除|find -deleteの安全手順 2026-09-07 07:45:13
- Django CBVでテンプレートに値を渡す|get_context_data・extra_context 2026-09-07 07:45:13
- Linuxで複数ファイルの文字列を一括置換|find・sed・xargsの安全手順 2026-09-07 07:45:13
- Laravelルートグループ|prefix・middleware・nameで一括管理 2026-09-07 07:45:13
- Linux whichコマンドの使い方|絶対パス取得とtype・command -vの違い 2026-09-07 07:45:13
- Linux catコマンドの使い方|行番号表示・複数ファイル連結 2026-09-07 07:45:13
- unable to execute 'gcc': No such file or directory 2026-09-07 07:45:13
コメントを削除してもよろしいでしょうか?