| この記事の要点 |
|
なぜ直書きしないのか
<!-- 直書き。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 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-10-03 21:41:49
- テンプレートフラグメント(ヘッダー等の共有化) 2026-10-03 21:41:49
- reCAPTCHA v3 使い方(サンプル付き) 2026-10-03 21:37:05
- Content-Type一覧|MIMEタイプとはとHTTPでの主な使用場面 2026-10-03 21:37:05
- SpringにおけるAOPの使い方 2026-10-03 21:37:05
- X (Twitter) API でツイートできないがエラーが出ない問題の原因と対処 2026-10-03 11:33:01
- X (Twitter) API アプリケーション登録完全ガイド|v2・Bearer Token・OAuth 2.0 PKCE 2026-10-03 11:33:01
- X (Twitter) API 完全ガイド|従量課金の料金・単価(2026年10月)と v2 移行 2026-10-03 11:32:40
- Google DeepMind とは?Gemini・AlphaFold の開発元 2026-10-03 11:26:56
- Cursor とは?AI 統合型コードエディタの使い方・料金 2026-10-03 11:26:56
- Claude (Anthropic) とは?AIチャットの使い方・モデルファミリ・API 2026-10-03 11:26:56
- AIベンダー一覧:OpenAI・Anthropic・Google DeepMind・Microsoft・Meta 2026-10-03 11:26:56
- クラウド・インフラ完全ガイド — AWS/Azure/GCP/Kubernetes 2026-10-03 11:26:56
- テキストエディタ完全比較 (VS Code / Cursor / Vim / Emacs / IDE) 2026-10-03 11:26:56
- プログラミング学習プラットフォーム|Scratch・micro:bit ほか 2026-10-03 11:26:56