【Django】urls.pyでルーティングを設定する基本

Django

こんにちは、かつコーチです。

前回の記事でDjangoのディレクトリ構成を紹介した際、「urls.pyはルーティングの起点になる」と説明しました。
この記事では、実際にurls.pyを編集しながら、URLと処理を結びつけるルーティング(どのURLにアクセスされたら、どの処理を実行するかの対応付け)の基本を解説します。

urls.pyの役割とは?

ルーティングとは何か

ルーティングとは、ブラウザから送られてきたURL(例:/blog/1/)を見て、「このURLならこの処理を実行する」と振り分ける仕組みのことです。
Djangoでは、この振り分けルールをurls.pyというファイルに記述します。

プロジェクトのurls.pyとアプリのurls.py

Djangoのルーティングには、2つのurls.pyが登場するのが特徴です。

  • プロジェクトのurls.pyconfig/urls.py):プロジェクト全体の入り口。どのアプリにルーティングを振り分けるかを管理する
  • アプリのurls.pyblog/urls.py):各アプリの中で、さらに細かくURLを振り分ける。デフォルトでは生成されないため自分で作成する

この2段階構成にすることで、アプリごとにURL設定を独立させられ、複数のアプリを組み合わせたときにも管理がしやすくなります。

urls.pyの基本の書き方

手順1:アプリのurls.pyを作成する

blogアプリの中に、urls.pyという名前でファイルを新規作成します。

# 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()関数の第1引数がURLのパターン、第2引数が呼び出す処理(View)、nameは後でURLを参照するときに使う名前です。
<int:pk>/のような書き方はパスコンバータと呼ばれ、URLの一部を数値として受け取り、Viewに引数として渡してくれます。

手順2:プロジェクトのurls.pyから読み込む

作成したアプリのurls.pyを、プロジェクト全体のurls.pyから読み込むように設定します。

# config/urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path("admin/", admin.site.urls),
    path("blog/", include("blog.urls")),
]

include()を使うことで、「/blog/から始まるURLはblog/urls.pyに処理を任せる」という委譲ができます。
これにより、/blog/にアクセスするとblog/urls.pypath("", ...)が、/blog/1/にアクセスするとpath("<int:pk>/", ...)が呼ばれる仕組みです。

手順3:対応するViewを用意する

urls.pyが参照しているviews.py側にも、対応する処理を書いておく必要があります。

# blog/views.py
from django.http import HttpResponse

def index(request):
    return HttpResponse("ブログ記事の一覧ページです")

def detail(request, pk):
    return HttpResponse(f"{pk}番の記事詳細ページです")

ここまで書けたら、開発サーバーを起動してhttp://127.0.0.1:8000/blog/http://127.0.0.1:8000/blog/1/にアクセスし、それぞれ別の文章が表示されることを確認してみましょう。

つまずきやすい設定・注意点

パスコンバータの種類を理解しておく

<int:pk>のように、パスコンバータにはいくつかの種類があります。

コンバータ用途
strデフォルト。スラッシュを含まない文字列
int0以上の整数
slug英数字・ハイフン・アンダースコアの文字列(記事URLなどに便利)
uuidUUID形式の文字列

用途に合わないコンバータを指定すると、意図したURLがマッチせず「404 Not Found」になってしまうので注意しましょう。

name属性を省略すると後で困る

path()name引数は省略してもエラーにはなりませんが、省略するとテンプレート側でURLを参照する際に困ります。

❌ Before
path("<int:pk>/", views.detail),
# nameがないため、テンプレートでURLを動的に組み立てられない
✅ After
path("<int:pk>/", views.detail, name="detail"),
# {% url 'blog:detail' pk=1 %} のように名前でURLを参照できる

筆者は最初、nameを「あとで付ければいいや」と省略して進めていたところ、テンプレートでリンクを作る段階になって大量に書き直す羽目になりました。
最初からnameを付けておく習慣をつけておくと、後の手戻りを防げます。

よくあるつまずきポイント・エラー対処

app_nameを付け忘れて名前空間エラーになる

❌ Before
NoReverseMatch: 'blog' is not a registered namespace

これは、アプリのurls.pyにapp_nameを設定しないまま、テンプレート側で{% url 'blog:detail' %}のように名前空間付きでURLを参照したときに出るエラーです。

✅ After
# blog/urls.py
app_name = "blog"  # この1行を忘れずに

urlpatterns = [
    path("<int:pk>/", views.detail, name="detail"),
]

複数のアプリを扱うようになると、detailのような名前が別のアプリでも使われて衝突することがあります。
app_nameで名前空間を区切っておくことで、こうした衝突を防げます。

応用・一歩先の使い方

includeの入れ子で大規模プロジェクトにも対応できる

アプリが増えてきた場合、プロジェクトのurls.pyには各アプリへのinclude()だけを並べる形にしておくと、見通しがよくなります。

# config/urls.py
urlpatterns = [
    path("admin/", admin.site.urls),
    path("blog/", include("blog.urls")),
    path("accounts/", include("accounts.urls")),
    path("shop/", include("shop.urls")),
]

このように「プロジェクトのurls.pyは交通整理役、各アプリのurls.pyが実際の詳細ルール」という役割分担を徹底すると、アプリ数が増えても管理しやすい構成を保てます。

まとめ

この記事のポイント

  • ルーティングは「URL」と「処理(View)」を結びつける仕組み
  • Djangoではプロジェクトのurls.pyとアプリのurls.pyの2段階構成が基本
  • include()でアプリ単位にルーティングを委譲する
  • path()nameapp_nameは最初から設定しておくと後で困らない

次に読むべき記事

URLと処理の結びつけ方が分かったら、次は実際にリクエストを処理する「関数ベースビュー(FBV)の書き方」で、Viewの中身を詳しく見ていきましょう。

タグ: Django, 初心者向け, フレームワーク基礎

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