ルーティングの基本とURLの処理
Djangoにおけるルーティングは、URLとビュー関数の対応関係を定義する仕組みです。URLの末尾にスラッシュがあるかどうかによって挙動が変わるため、設定ファイルsettings.pyでAPPEND_SLASH = Falseを設定することで、スラッシュなしのリクエストを自動でリダイレクトしないように調整可能です。
基本的なルーティング構文:
from django.urls import path
from . import views
urlpatterns = [
path('index/', views.index),
]
動的URLとpath変換器
Django 2.x以降では、URLの一部を動的に扱うためにpath変換器が提供されています。例えば、整数や文字列を抽出する際に利用します。
path('user//', views.user_detail),
path('article//', views.article_detail)
int: 正の整数または0str: パス区切り文字以外の文字列slug: 英数字とハイフン、アンダースコアuuid: UUID形式path: 任意のパス全体
正規表現によるルーティング
複雑なURLのパターンを扱うにはre_pathを使用します。これはDjango 1.xのurl()と同等の機能です。
from django.urls import re_path
from . import views
urlpatterns = [
re_path(r'^test/$', views.test),
re_path(r'^test/(\d{4})/$', views.test_year),
re_path(r'^test/(?P<year>\d{4})/$', views.test_named_year),
]
- 無名グループ:
(\d{4})→ 位置引数としてビューに渡される - 有名グループ:
(?P→ キーワード引数としてビューに渡される\d{4})
※無名グループと有名グループは混在させることができません。
逆引き(リバース)ルーティング
URLの変更に対応するために、ルーティングに名前を付けて逆引きする機能です。
path('login/', views.login, name='login_page')
- テンプレート内:
{% url 'login_page' %} - ビュー関数内:
from django.shortcuts import reverse; reverse('login_page')
動的URLの逆引き:
path('profile//', views.profile, name='profile_page')
- テンプレート:
{% url 'profile_page' 'alice' %} - ビュー関数:
reverse('profile_page', args=['alice'])
ルーティングの分離とアプリケーションの分割
大規模なプロジェクトでは、すべてのルーティングを1つのファイルに書くのは管理が困難です。Djangoではアプリケーションごとにurls.pyを設け、メインルーティングでinclude()を使って分離できます。
# メインurls.py
from django.urls import include, path
urlpatterns = [
path('blog/', include('blog.urls')),
path('shop/', include('shop.urls')),
]
名前空間と逆引きの競合回避
複数アプリケーションで同じ名前のルーティングが存在する場合、名前空間を指定することで区別できます。
# メインurls.py
path('blog/', include('blog.urls', namespace='blog')),
path('shop/', include('shop.urls', namespace='shop')),
# blog/urls.py
app_name = 'blog'
urlpatterns = [
path('post//', views.post_detail, name='detail'),
]
# shop/urls.py
app_name = 'shop'
urlpatterns = [
path('product//', views.product_detail, name='detail'),
]
- ビュー関数内:
reverse('blog:detail', args=[10]) - テンプレート:
{% url 'shop:detail' 5 %}
名前空間を使わず、名前をアプリケーション名でプレフィックスする方法もあります:
path('post//', views.post_detail, name='blog_detail')