Python | Web フレームワーク:URLconf

Python
スポンサーリンク

概要(URLconf=「URL とビューを結びつける交通整理係」)

Django の URLconf(URL configuration)は、

「どの URL にアクセスされたときに、どのビューを呼ぶか」

を決める設定です。
Django の世界では、ユーザーがブラウザで URL を叩くたびに、
まずこの URLconf が「どのビューに処理を渡すか」を判断します。

イメージとしては、
URLconf は「入り口の案内板」、ビューは「実際に仕事をする人」です。
URLconf が「この URL はこの人(ビュー)にお願いね」と振り分けてくれるから、
アプリ全体の動きが整理されます。

ここから、

URLconf の基本構造
プロジェクトレベルとアプリレベルの urls.py の役割
path とパスコンバータ(int:id ( in Bing) など)の意味
include を使った URL の分割設計
名前付き URL と reverse の考え方

を、初心者向けにかみ砕いて説明していきます。


URLconf の基本構造をつかむ

urls.py に書くのは「URLパターンとビューの対応表」

Django プロジェクトを作ると、
プロジェクト直下に project/urls.py ができます。
中身はだいたいこんな形です。

from django.contrib import admin
from django.urls import path

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

ここで大事なのは、urlpatterns という変数です。
これは「URL パターンの一覧」で、
Django はここに書かれた順番に URL を照合していきます。

path("admin/", admin.site.urls) は、

「/admin/ にアクセスされたら admin.site.urls に処理を渡す」

という意味です。
admin.site.urls も実は URLconf なので、
URLconf から別の URLconf にバトンを渡しているイメージです。

URLconf の本質は、

「URL の文字列パターン」と「ビュー(または別の URLconf)」の対応表

だと捉えてください。

path 関数の基本形

path() の基本形はこうです。

path("パス文字列/", 呼び出すビュー, name="任意の名前")
Python

例えば、トップページ用のビューがあるとします。

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

def index(request):
    return HttpResponse("Hello Django")
Python

これを URL に紐づけるには、urls.py にこう書きます。

from django.urls import path
from . import views

urlpatterns = [
    path("", views.index, name="index"),
]
Python

"" は「ルート(/)」を意味します。
これで http://localhost:8000/ にアクセスすると、
index ビューが呼ばれます。

ここで押さえたいのは、

URLconf は「どの URL でどのビューを呼ぶか」を
path() の並びとして書いていく場所

ということです。


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

プロジェクト全体の入り口としての project/urls.py

プロジェクトを作ったときにできる project/urls.py は、
「サイト全体の入り口」です。

ユーザーからのリクエストは、まずここに来ます。
ここで、

管理画面は /admin/ に振り分ける
アプリ A は /blog/ 以下に振り分ける
アプリ B は /shop/ 以下に振り分ける

といった「大まかな振り分け」を行います。

例えば、blog アプリと shop アプリがある場合はこう書きます。

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

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

include("blog.urls") は、
「/blog/ で始まる URL は、blog アプリの urls.py に続きを任せる」
という意味です。

アプリごとの urls.py で「そのアプリの担当部分」を書く

各アプリ側にも blog/urls.py のようなファイルを作り、
そのアプリに関係する URL をまとめます。

# blog/urls.py
from django.urls import path
from . import views

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

これで、

/blog/ → post_list ビュー
/blog/1/ → post_detail ビュー(pk=1)
/blog/2/ → post_detail ビュー(pk=2)

という対応になります。

この構造のメリットは、

プロジェクト全体の urls.py は「大きな入口の振り分け」だけ
各アプリの urls.py は「そのアプリの中の細かい URL」だけ

と役割を分けられることです。
アプリが増えても、URLconf が整理されたまま保てます。


パスコンバータ(int:id ( in Bing) など)の意味と使い方

URL の一部を「変数」としてビューに渡す

Django の path では、
URL の一部を「変数」としてビューに渡すことができます。

例えば、記事の ID を URL から受け取りたい場合。

# blog/urls.py
urlpatterns = [
    path("<int:pk>/", views.post_detail, name="post_detail"),
]
Python

<int:pk> の部分が「パスコンバータ」です。
これは、

URL のその部分を整数として解釈し、
ビュー関数の引数 pk に渡す

という意味になります。

ビュー側はこう書きます。

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

def post_detail(request, pk):
    return HttpResponse(f"記事ID: {pk}")
Python

/blog/10/ にアクセスすると、
pk=10 がビューに渡されます。

よく使うパスコンバータの種類

代表的なものだけ覚えておけば十分です。

<int:pk> 整数
<str:slug> 文字列(スラッシュ以外)
<slug:slug> スラッグ(英数字とハイフンなど)
<path:path> スラッシュを含むパス全体

初心者のうちは、
「ID なら <int:id>、文字列なら <str:name>
くらいを使いこなせれば OK です。

ここで大事なのは、

URL の一部を「ビューの引数」として受け取れる
そのときに「型」も一緒に指定できる

という感覚です。


include で URL を分割する設計の考え方

URLconf を「モジュール化」する

アプリが増えたり、URL が多くなってくると、
一つの urls.py に全部書くのはつらくなります。

Django の include() は、
URLconf を分割してモジュール化するための仕組みです。

プロジェクトの urls.py では、
大きな入口だけを定義します。

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

各アプリの urls.py では、
そのアプリに関係する URL だけを書きます。

こうすることで、

URL の責任範囲がアプリごとに分かれる
アプリを別プロジェクトに持っていくときも移植しやすい

というメリットが生まれます。

URLconf を設計するときは、

「この URL はどのアプリの責任か」

を意識して、
include でうまく分割していくと、
長期的にかなり楽になります。


名前付き URL と reverse の考え方(ここが実務で超重要)

URL を「文字列」ではなく「名前」で参照する

Django では、URL に name を付けることができます。

# blog/urls.py
urlpatterns = [
    path("", views.post_list, name="post_list"),
    path("<int:pk>/", views.post_detail, name="post_detail"),
]
Python

この name="post_detail" のような名前は、
テンプレートやビューの中で「URL を逆引きする」ために使います。

テンプレートでは、url タグでこう書けます。

<a href="{% url 'post_detail' pk=post.id %}">{{ post.title }}</a>
Python

ここで {% url 'post_detail' pk=post.id %} は、
post_detail という名前の URL パターンを探し、
pk に post.id を埋め込んだ URL を生成します。

例えば、post.id が 10 なら /blog/10/ になります。

なぜ「名前で参照する」のが大事なのか

もしテンプレートに直接 /blog/10/ のような URL をベタ書きしてしまうと、
URL パターンを変更したときに、
テンプレートのあちこちを修正しなければなりません。

しかし、name を使っていれば、

path("<int:pk>/", views.post_detail, name="post_detail")

path("posts/<int:pk>/", views.post_detail, name="post_detail")

のように変えても、
テンプレート側は {% url 'post_detail' pk=post.id %} のままで OK です。

つまり、

URL の実際の文字列は urls.py に閉じ込める
他の場所(テンプレートやビュー)は「名前」で参照する

という設計にしておくと、
URL の変更に強いアプリになります。

ビュー側でも、reverse()reverse_lazy() を使って
同じように URL を名前から生成できます。


まとめ(URLconf は「アプリ全体の入り口を設計する場所」)

Django の URLconf を初心者向けに整理すると、こうなります。

URLconf(urls.py)は、「どの URL でどのビューを呼ぶか」を定義する設定で、Django はリクエストが来るたびに urlpatterns を上から順に見て、最初にマッチしたパターンのビューを実行する。
プロジェクトレベルの urls.py は「サイト全体の入り口」を担当し、各アプリの urls.py は「そのアプリの中の URL」を担当する。include() を使うことで URLconf をアプリごとに分割できる。
path() のパスコンバータ(int:pk ( in Bing) など)を使うと、URL の一部をビューの引数として受け取れる。これにより「/blog/10/ → post_detail(pk=10)」のような自然な URL を設計できる。
name を付けた URL を {% url 'name' %} や reverse() で参照することで、「URL の実際の文字列」を urls.py に閉じ込め、他のコードは「名前」だけを知っていればよい状態にできる。

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