URL ディスパッチャ

revision-up-to:17812 (1.4)

すっきりした、簡潔で明解な URL スキームの設計は、高品質の Web アプリケーショ ンでは重要な要素です。 Django では、フレームワークの制限なしに、望み通りの URL を設計できます。

.php.cgi といった拡張子は必要なく、 0,2097,1-1-1928,00 のよ うな意味不明の URL にする必要もありません。

URL はすっきりした扱いやすいものにすべきであるという主張については、ワール ドワイドウェブの産みの親である Tim Berners-Lee の優れた解説、 Cool URIs don’t change を参照してください。

概要

あるアプリケーション向けの URL を設計するには、 URLconf (URL 設定: URL configuration) と呼びならわされている Python モジュールを作成します。このモ ジュールは pure Python のコードで、中にはただ URL パターン (単純な正規表現) から Python のコールバック関数 (自作のビュー) へのマッピングが入っているだ けです。

Django 1.4 で新たに登場しました: Django はまた、 URL が稼働している言語から翻訳することを許可しています。 このプロセスは、 internationalization docs で、説明 しています。

このマッピングは短くもできますし、必要なだけ長くもできます。他のマッピング も参照できます。また、 pure Python コードなので、動的に生成できます。

Django のリクエスト処理

ユーザが Django で作られたサイト上のページをリクエストした時に、どの Python コードが実行されるかは以下のアルゴリズムで決定されます:

  1. まず、Django は、どのモジュールをルート URLconf として使うか決定しま す。もともとは、この値は ROOT_URLCONF に設定されています。ただし、 HttpRequest オブジェクトに urlconf という属性が設定されてい た場合( request processing で設定されます) 、その値を ROOT_URLCONF の代わりに使います。
  2. Django は上記の Python モジュールをロードして、 urlpatterns とい う名前の変数を探します。この変数の値は Python のリストで、 django.conf.urls.patterns() が返すのと同じ形式です。
  3. Django は URL パターンを順に調べて、リクエスト URL に最初にマッチし たところで止まります。
  4. 何らかの正規表現にマッチしたら、 Django はマッピングされているビュー を import して呼び出します。ビューは単純な Python 関数です。ビュー関 数の第一引数には HttpRequest が、それ以降の引 数には正規表現でキャプチャした値が渡されます。
  5. もし、正規表現が何にもマッチしなかったり、パターンマッチングプロセスの 途中のどこかで例外が発生した場合、 Django は、適切なエラーハンドリング ビューを呼び出します。 エラーハンドリング を見てください。

凡例

URLconf の一例を示します:

from django.conf.urls import patterns, url, include

urlpatterns = patterns('',
    (r'^articles/2003/$', 'news.views.special_case_2003'),
    (r'^articles/(\d{4})/$', 'news.views.year_archive'),
    (r'^articles/(\d{4})/(\d{2})/$', 'news.views.month_archive'),
    (r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'news.views.article_detail'),
)

注意:

  • URL 中の値を取り出すには、単に丸括弧で囲むだけです。
  • 先頭のスラッシュは必要ありません。全ての URL に共通だからです。例えば、 ^/articles ではなく ^articles にします。
  • 正規表現文字列のリテラルの前に 'r' があります。これは必須ではあり ませんが、付けた方がよいでしょう。 r は、”raw” 文字列、すなわち文 字列中のいかなる文字もエスケープしないことを表します。 Dive Into Python’s explanation も参考にしてください。

例のリクエストを挙げて説明しましょう:

  • /articles/2005/03/ へのリクエストは 3 つめのエントリにマッチしま す。 Django は news.views.month_archive(request, '2005', '03') を 呼び出します。
  • /articles/2005/3/ はどの UrL パターンにもマッチしません。リストの 3 つめのエントリでは月番号が 2 桁になるよう要求しているからです。
  • /articles/2003/ はリストの 2 番目ではなく、最初のパターンにマッチ します。パターンは順番に調べられ、最初にテストにパスしたものが使われ るからです。この法則を、特別扱いしたい URL の処理に使ってもかまいませ ん。
  • /articles/2003 は URL がスラッシュで終わっていないので、どのパター ンにもマッチしません。
  • /articles/2003/03/3/ は最後のパターンにマッチします。 Django は news.views.article_detail(request, '2003', '03', '3') を呼び出し ます。

名前つきグループ

上の例では、 名前なしの 簡単な正規表現グループを (丸括弧表記で) 使って URL から情報を取り出し、ビュー関数に 固定引数 として渡していました。より 高度な方法に、 名前つきの 正規表現グループで URL から情報を取り出し、ビュー の キーワード引数 に渡すものがあります。

Python の正規表現では、名前つき正規表現グループは、 name をグループの名 前、 pattern をマッチさせるパターンとして、 (?P<name>pattern) で表 されます。

上の URLconf の例を書き換えて、名前つきグループにしたものを示します:

urlpatterns = patterns('',
    (r'^articles/2003/$', 'news.views.special_case_2003'),
    (r'^articles/(?P<year>\d{4})/$', 'news.views.year_archive'),
    (r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/$', 'news.views.month_archive'),
    (r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})/$', 'news.views.article_detail'),
)

この URLconf は前の例と全く同じ機能を実現しますが、一つだけはっきり違うのは、 取り出した値を固定引数ではなくキーワード引数としてビュー関数に渡すという点 です。例えば:

  • /articles/2005/03/ へのリクエストは、 news.views.month_archive(request, year='2005', month='03') ではなく news.views.month_archive(request, '2005', '03') を呼び出します。
  • /articles/2003/03/3/ へのリクエストは news.views.article_detail(request, year='2003', month='03', day='3') を呼び出します。

実際には、このような名前つきグループを使うと URLconf が少しだけ明示的な書き 方になり、引数の順番に起因するバグを起こしにくくなります – それに、自作ビュー の関数定義で引数順を変更できます。いうまでもなく、こうした恩恵は簡潔さの犠 牲の上に成り立っています: 開発者の中には、名前つきグループの構文が醜くて冗長 だと感じる人もいます。

マッチ/グルーピングのメカニズム

URLconf パーザが正規表現中の名前つきグループと名前なしグループを扱う際のア ルゴリズムを以下に示します:

名前つきの引数があればそれを使います。名前なし引数は無視します。名前つきの 引数がなければ、すべての名前なし引数を固定引数として使います。

どちらの場合でも、追加のキーワード引数を指定できます。後述の「ビュー関数に 追加のオプションを渡す」を参照してください。

URLconf の検索対象

URLconf はリクエストされた URL を通常の Python 文字列として検索します。この 文字列には GET や POST のパラメタも、ドメイン名も入りません。

例えば、 http://www.example.com/myapp/ URLconf が検索対象にするのは myapp/ です。

http://www.example.com/myapp/?page=3 へのリクエストの場合でも myapp/ です。

URLconf はリクエストメソッドを調べません。換言すれば、同じ URL に対する POST, GET, HEAD といった全てのリクエストメソッドは同じビュー関 数に送られます。

urlpatterns の書き方

urlpatternsdjango.conf.urls.patterns`() の返す形式の Python リストになります。 urlpatterns 変数の値を作るときには、常に patterns() を使うようにして下さい。

django.conf.urls 汎用的な関数

Django 1.4 で撤廃されました:

Deprecated since version 1.4: Django 1.4 の関数 patterns, url, include に加えて handler*django.conf.urls モジュールの中にあり、以下で説明さ れているシンボル群です。

Django 1.3 までは、これらは django.conf.urls.defaults の中に位置していました。まだ、以前のモジュールからインポート することが出来ますが、 Django 1.6 でそれが出来なくなります。

patterns

patterns(prefix, pattern_description, ...)

プレフィクス (prefix) 引数、および任意の個数の URL パターンをとり、Django で必要な形式の URL パターンのリストを返す関数です。

patterns() の最初の引数は プレフィクス (prefix) 文字列です。後述の 「 ビュープレフィクス 」 を参照してください。

残りの引数は以下の形式のタプルにします:

(正規表現, Pythonコールバック関数 [, パラメタ辞書 [, エントリ名]])

パラメタ辞書 および エントリ名 はオプションで、省略できます (詳しくは「 ビュー関数に追加のオプションを渡す 」を参照してください)。

Note

patterns() は関数呼びだしの形式を取っているので、取れる引数 (URL パ ターン) は最大 255 個に制限されています。これは全ての Python 関数呼びだ しに共通する制約です。通常は、 URL パターンを include() でモジュラ に構造化するものなので、事実上この制約はほとんど問題になりません。とは いえ、運悪く 255 個の制約に引っかかってしまうようなら、 pattern() が Python のリストを返すということを思い出して、以下のように引数を分割 し、リストを構築するとよいでしょう:

urlpatterns = patterns('',
    ...
    )
urlpatterns += patterns('',
    ...
    )

Python のリスト型にはサイズ制限がありませんから、いくつでも URL パター ンを定義できます。ただし、一度に 254 個づつ (先頭のプレフィクス引数のた めに、 255 個のうちの一つを使います) しか定義できないという制約に注意し てください。

url

url(regex, view, kwargs=None, name=None, prefix='')

url() 関数は、タプルの代わりとして patterns() の引数に指定できます。 この関数は、パラメタ辞書がないときに URLconf のエントリ名を指定したい場合に 便利です。例えば、以下のように用います:

urlpatterns = patterns('',
    url(r'/index/$', index_view, name="main-view"),
    ...
)

この関数は 5 つの引数をとり、そのほとんどが省略可能です:

url(regex, view, kwargs=None, name=None, prefix='')

name パラメタが便利な理由は「 URL パターンに名前を付ける 」の節を参 照してください。

prefix パラメタは patterns() の最初の引数と同じ意味を持ち、 view を文字列形式で指定する場合にしか使われません。

include

include(<module or pattern_list>)

関数は現在の URLconf で “included” しておくべき Python のフル import パス を他の URLconf モジュールへと 取りこみます。

include() も引数としてイテレート可能です。これは、 URL パターンを返します。

他の URLconf を取り込む を見てください。

エラーハンドリング

Django が、リクエストされた URL にマッチする正規表現を 見つけられなかったとき、または例外が発生したとき、 Django は error-handling view を発生させます。ビューはルートの URlconf に設定された三つの変数で、指定されたケースで使用 されます。これらの変数の設定は、他のどの URLconf にも影響を 与えません。

エラービューのカスタマイズ を参照してください、もっと詳しいことが載っています。

handler403

handler403

呼ぶことができます、またはユーザがリソースにアクセスするのに 必要なパーミッション(permission 権限)を持っていない場合に、 ビュー関数への完全な Python の import パスが入った文字列です。

通常、これは 'django.views.defaults.permission_denied' これのデフォルト値は満足させるでしょう。

403 (閲覧が禁止されています ビュー) にもっと沢山の情報が載っています。

Django 1.4 で新たに登場しました: handler403 は Django 1.4の新しいものです

handler404

handler404

呼び出せるか、マッチする URL パターンがない場合に呼び出されるビュー関数への、 完全な Python の import パスが入った文字列です。

デフォルト値は、 'django.views.defaults.page_not_found' です。 普通はこのデフォルト値で十分のはずです。

Django 1.2 で変更されました: 前のバージョンの Django では、 import パスが入った文字列のみを、受け取れ ます。

handler500

handler500

呼び出しか、サーバエラーが生じた場合に呼び出されるビュー関数への、 完全な Python の import パスが入った文字列です。 サーバエラーはビュー関数のコード中で実行時エラーが生じたときに起きます。

デフォルト値は、 'django.views.defaults.page_not_found' です。 普通はこのデフォルト値で十分のはずです。

Django 1.2 で変更されました: 前のバージョンの Django では、 import パスが入った文字列のみを、受け取れ ます。

URL 中のテキストを取り出す際の注意

引数として取り出したテキストは、正規表現が何にマッチするかに関係なく通常の Python 文字列型になります。例えば、下のような URLconf の行:

(r'^articles/(?P<year>\d{4})/$', 'news.views.year_archive'),

では、 news.views.year_archive() に渡される year 引数は、整数ではな くあくまでも文字列になります。 \d{4} が整数を表す文字列にしかマッチしな いことは関係ありません。

よく使うトリックとして、ビュー関数の引数にデフォルトパラメタを指定しておく という方法があります。 URLconf とビューの一例をあげて説明しましょう:

# URLconf
urlpatterns = patterns('',
    (r'^blog/$', 'blog.views.page'),
    (r'^blog/page(?P<num>\d+)/$', 'blog.views.page'),
)

# View (in blog/views.py)
def page(request, num="1"):
    # Output the appropriate page of blog entries, according to num.

上の例では、 URL パターンはどちらも同じビュー、 blog.views.page を指し ています。しかし、最初のパターンでは、 URL から何の情報も取り出しません。最 初のパターンがマッチすると、 page() 関数は num の値として、デフォル トの "1" を使います。二つめのパターンがマッチすると、 page() は正規 表現で取り出した num の値を使います。

パフォーマンス

urlpatterns 内の各正規表現は、最初にアクセスした際にコンパイルされます。 これによって、システムは劇的に高速になります。

ビュープレフィクス

コードを繰り返し書かなくてもよいように、 patterns() 呼び出しの中で共通 のプレフィクスを指定できます。

Django の概要 からとってきた URLconf の例を示します:

from django.conf.urls import patterns, url, include

urlpatterns = patterns('',
    (r'^articles/(\d{4})/$', 'news.views.year_archive'),
    (r'^articles/(\d{4})/(\d{2})/$', 'news.views.month_archive'),
    (r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'news.views.article_detail'),
)

この例では、各ビューには共通のプレフィクス、 'news.views' があり ます。 urlpatterns の各エントリに繰り返し入力する代わりに、 patterns() 関数の最初の引数にプレフィクスを指定して、各ビュー関数に適用 できます。

このことを念頭に置いて、上記の例をもっと簡潔に書くと以下のようになります:

from django.conf.urls import patterns, url, include

urlpatterns = patterns('news.views',
    (r'^articles/(\d{4})/$', 'year_archive'),
    (r'^articles/(\d{4})/(\d{2})/$', 'month_archive'),
    (r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'article_detail'),
)

プレフィクスには末尾のドット (".") を入れていないことに注意してください。 Django はドットを自動的に入れます。

複数のビュープレフィクス

現実的には、色々なビューを取り混ぜて使うことになり、 urlpatterns に共通 のプレフィクスを持たせられなくなることでしょう。しかし、パターンの重複を防 ぐビュープレフィクスのショートカット機能には、もう一つの利用法があります。 それは、以下のように複数の patterns() オブジェクトを足し合わせるという ものです:

古い書き方:

from django.conf.urls import patterns, url, include

urlpatterns = patterns('',
    (r'^$', 'django.views.generic.date_based.archive_index'),
    (r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$', 'django.views.generic.date_based.archive_month'),
    (r'^tag/(?P<tag>\w+)/$', 'weblog.views.tag'),
)

は、以下のような書き方に改められます:

from django.conf.urls import patterns, url, include

urlpatterns = patterns('django.views.generic.date_based',
    (r'^$', 'archive_index'),
    (r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$','archive_month'),
)

urlpatterns += patterns('weblog.views',
    (r'^tag/(?P<tag>\w+)/$', 'tag'),
)

他の URLconf を取り込む

urlpatterns 好きな場所で、他の URLconf モジュール上の定義を取り込めます。 この操作は、本質的には一連の URL を他の URLconf の下に「すげかえる(root)」 操作になります。

例として、 Django ウェブサイト 自体の URLconf の例外を示します。この URLconf は他の URLconf をいくつも取り込んでいます:

from django.conf.urls import patterns, url, include

urlpatterns = patterns('',
    # ... snip ...
    (r'^comments/', include('django.contrib.comments.urls')),
    (r'^community/', include('django_website.aggregator.urls')),
    (r'^contact/', include('django_website.contact.urls')),
    (r'^r/', include('django.conf.urls.shortcut')),
    # ... snip ...
)

この例の正規表現が、 $ (行末にマッチする文字) を使っておらず、末尾にスラッ シュを付けていることに注意しましょう。 Django が include() をみつけると、 URL からマッチした部分を取り去り、残りの文字列を include された URLconf に 送って続きの処理を行わせます。

URLconf を Python モジュールで include 引数で指定する方法ではなく、 追加した URL patterns を含める別の可能性として、 patterns によって 返されたパターンリストを直接的に使う方法があります。:

from django.conf.urls import patterns, url, include

extra_patterns = patterns('',
    url(r'^reports/(?P<id>\d+)/$', 'credit.views.report', name='credit-reports'),
    url(r'^charge/$', 'credit.views.charge', name='credit-charge'),
)

urlpatterns = patterns('',
    url(r'^$',    'apps.main.views.homepage', name='site-homepage'),
    (r'^help/',   include('apps.help.urls')),
    (r'^credit/', include(extra_patterns)),
)

この手法は、 Django のアドミンアプリケーションのインスタンスを配置する時に 見られます。 Django のアドミンは、 AdminSite のインスタンスとして 配置されます。それぞれの ~django.contrib.admin.AdminSite インスタンスは urls アトリビュートを持っていて、 それらは url パターンとしてインスタンスに使用可能です。 それは、アドミンのインターフェイスを配置する時に、 include() を プロジェクトの urlpatterns に入れることができます。

キャプチャされたパラメタ

include された側の URLconf は、親となる URLconf で取り出された全てのパラメ タを受け継ぎます。従って、以下のような例はうまく動作します:

# In settings/urls/main.py
urlpatterns = patterns('',
    (r'^(?P<username>\w+)/blog/', include('foo.urls.blog')),
)

# In foo/urls/blog.py
urlpatterns = patterns('foo.views',
    (r'^$', 'blog.index'),
    (r'^archive/$', 'blog.archive'),
)

上の例では、 include された側にも "username" 変数が期待どおりに渡されま す。

URL の名前空間を定義する

もし、複数のインスタンスを一つのアプリケーションで必要としたならば、 インスタンスの間で区別を付けられることが役立つでしょう。 これは、一つのアプリケーションが分割する URL の名前付けの 複数のインスタンスにおいて URL の名前付け を使う時に 特に大切になります。一つのアプリケーションの中の複数の インスタンスは、名前づけられた URL を分割します、名前空間は インスタンスそれぞれに名前づけられた URL の分割を教える方法です。

URL の名前空間は二つのパートになります、両方とも文字列です:

  • 一つは application namespace です。これはデプロイ(deploy)されている アプリケーションの名前を示します。単一のアプリケーションの全てのインスタンス は、同じアプリケーションの名前空間 を持ちます。例えば、 Django のアドミンアプリケーションは幾分予測可能な アプリケーションの名前空間を持っています admin です。
  • そして、 instance namespace です。この識別子はアプリケーションの特有の インスタンスです。インスタンスの名前空間は、プロジェクト全体に渡り、 一意のものです。これはアプリケーションの通常のインスタンスを指定するために 使われます。例えば、通常 Django のアドミンインスタンスは admin の インスタンスの名前空間を持っています。

URL の名前空間は二つの方法によって指定されています。

始めに、URL パターンを構成する時、アプリケーションとインスタンスの名前空間を、 include() の引数として、渡すことができます。:

(r'^help/', include('apps.help.urls', namespace='foo', app_name='bar'))

これは apps.help.urls のなかで定義された URL を含み、インスタンスの 名前空間 bar と、アプリケーションの名前空間 foo へといきます。

二つ目は、埋め込まれた名前空間のデータを内包するオブジェクトを含むことができま す。もし、 patterns オブジェクトを include() したなら、オブジェクトは グローバルな名前空間へと加えられます。しかしながら、三つのタプルを 含んだオブジェクトを include() することもできます:

(<patterns object>, <application namespace>, <instance namespace>)

これは、与えられたアプリケーションとインスタンスの名前空間へと指定された URL パターンを含みます。例えば、 Django の AdminSite オブジェクトの urls アトリビュートは 3つのタプルを返し、それはアドミンサイトの 全てのパターンを含んでいます。そして、アドミンインスタンスの名前を足すと アプリケーション名前空間の admin です。

一度定義した、名前空間化された URL は、名前空間から逆引きしてたどること が出来ます。もっと詳しく、名前空間づけた URL を逆引きする方法について知るには、 URL 名前空間 を見てください。

ビュー関数に追加のオプションを渡す

URLconf には、ビュー関数に追加の引数を Python の辞書型で渡せるようにするた めのフックがあります。

URLconf タプルにはオプションとして 3 つめの要素を指定できます。この要素は ビューに渡したい追加の引数からなる辞書にします。

例えば:

urlpatterns = patterns('blog.views',
    (r'^blog/(?P<year>\d{4})/$', 'year_archive', {'foo': 'bar'}),
)

この例では、 /blog/2005/ というリクエストに対し、 Django は blog.views.year_archive() ビューを呼び出し、以下のキーワード引数を渡し ます:

year='2005', foo='bar'

このテクニックは 汎用ビュー配信フィードフレームワーク で、メタデータ やビューへのオプションを渡すために使われています。

衝突を避ける

URLconf を書くとき、名前付きのキーワード引数をキャプチャさせ、同時に追 加引数の辞書に同名の項目を追加するような書き方ができてしまいます。この 場合、辞書に設定した内容が優先されます。

include() に追加のオプションを渡す

include() にも追加のオプションを渡せます。 include() に追加のオプショ ンを渡すと、そのオプションは include された側の URLconf の 全ての URL 設定 に適用されます。

例えば、以下の二つの URLconf は機能的に全く同じです:

その 1:

# main.py: include する側
urlpatterns = patterns('',
    (r'^blog/', include('inner'), {'blogid': 3}),
)

# inner.py: include される側
urlpatterns = patterns('',
    (r'^archive/$', 'mysite.views.archive'),
    (r'^about/$', 'mysite.views.about'),
)

その 2:

# main.py: include する側
urlpatterns = patterns('',
    (r'^blog/', include('inner')),
)

# inner.py: include される側
urlpatterns = patterns('',
    (r'^archive/$', 'mysite.views.archive', {'blogid': 3}),
    (r'^about/$', 'mysite.views.about', {'blogid': 3}),
)

追加オプションは、ビューがオプションを実際に有効なオプションとして受け取る かどうかに関わらず、 常に include される側の URLconf の 全ての 行に渡さ れるので注意してください。このため、 include に追加オプションを渡すテクニッ クが有効なのは、include される側の URLconf に入っている全てのビューが、追加 のオプションを受け取れるとはっきりしている場合だけです。

文字列の代わりに呼び出し可能オブジェクトを渡す

開発者の中には、ビューのパスが入った文字列の代わりに、ビューそのものを表す Python 関数オブジェクトを渡す方が自然だと考えている者もいます。この代替案も サポートされており、任意の呼び出し可能オブジェクトをビューに渡せます。

例えば、 以下のような「文字列の」URLconf があったとします:

urlpatterns = patterns('',
    (r'^archive/$', 'mysite.views.archive'),
    (r'^about/$', 'mysite.views.about'),
    (r'^contact/$', 'mysite.views.contact'),
)

文字列の代わりにオブジェクトを渡して、同じ機能の URLconf を実現できます。オ ブジェクトを忘れず import してください:

from mysite.views import archive, about, contact

urlpatterns = patterns('',
    (r'^archive/$', archive),
    (r'^about/$', about),
    (r'^contact/$', contact),
)

以下の例も機能的に全く同じです。個々のビューを個別に import する代わりにビュー の入ったモジュールを import すると、すこしだけすっきり書けます:

from mysite import views

urlpatterns = patterns('',
    (r'^archive/$', views.archive),
    (r'^about/$', views.about),
    (r'^contact/$', views.contact),
)

どのスタイルを使うかは自由です。

このテクニックを使った場合 (文字列の代わりにオブジェクトを渡した場合) 上で説明した “”ビュープレフィクス”” は効果を及ぼさないので注意してください。

URL パターンに名前を付ける

URLconf 中の複数の URL パターンから同じビュー関数を呼ぶケースはよくあります。 たとえば、以下の二つの URL パターンは、どちらも archive というビューを 指しています:

urlpatterns = patterns('',
    (r'/archive/(\d{4})/$', archive),
    (r'/archive-summary/(\d{4})/$', archive, {'summary': True}),
)

この URLconf には何ら問題はないのですが、 (permalink() デコレータや {% url %} を使って) 逆引き URL マッチング (reverse URL matching) を 行うと問題を引き起こします。というのも、二つの URLパターンが同じビューを指 しているために、Django の逆引き URL マッチング機構は、 archive ビューに 対する正しい URL がわからなくなってしまうからです。

この問題を解決するために、Django は 名前付き URL パターン をサポートし ています。すなわち、各 URL パターンに名前をつけて、同じビューやパラメタを使っ ているパターンどうしを区別できます。その上で、付けた名前を使って逆引き URL マッチングを行えます。

例えば、 URLconf が以下のようになっていたとしましょう:

urlpatterns = patterns('',
    url(r'/archive/(\d{4})/$', archive, name="full-archive"),
    url(r'/archive-summary/(\d{4})/$', archive, {'summary': True}, "arch-summary"),
)

上記に記した名前(full-archive and arch-summary)を使って、個別にそれ ぞれのパターンの URL にアクセスすることができます。

{% url arch-summary 1945 %}
{% url full-archive 2007 %}

つまり、二つの URL パターンがどちらも同じく archive ビューを参照してい ても、 url()name パラメタを指定すれば、テンプレート中で二つを区 別できるというわけです。

URLconf エントリに付ける名前は、どんな文字を入れても構いません。 Python の 変数名規則には縛られません。

Note

URLconf エントリに名前を付ける場合、他のアプリケーションの名前と衝突し なさそうな名前を使ってください。例えば、ある URL パターンを “comment” と命名していて、他のアプリケーションでも同じ名前を使っていたとしましょ う。この名前をテンプレートで使うと、もはやどちらの URL がテンプレートに 挿入されるのか判断する術はありません。

URLconf エントリの名前に、例えばアプリケーション名などからとったプレフィ クスを追加しておけば、名前が衝突しにくくなってよいでしょう。というわけ で、単に “comment” ではなく、 “myapp-comment” にするよう勧めます。

URL 名前空間

名前空間化された URL は : 演算子を使うことによって指定されます。 例えば、アドミンアプリケーションの、メインのインデックスページは admin:index を使うことによって参照されます。

名前空間は、ネスト(nest 入れ子)することができます。 foo:bar:whiz と名前づけられた URL は、トップレベルの名前空間である foo の中から bar という名前で定義されたものを探し、さらにその中から whiz という名前のパターンを探します。

名前空間化された URL (すなわち、myapp:index のようなもの) が与えられる て解決すると、 Django は完全にパス化されたものをパーツごとに分解しようとしま す。そしてその時に、 URL の探索を行おうとします。

  1. 最初に、 Django はアプリケーションの名前空間とマッチするものを探そうとし ます。(この例では myapp です。)これは、アプリケーションのインスタンスの リストを作ります。

  2. もし、 現在の アプリケーションが定義されていれば、 Django は インスタンスの為に URL リゾルバを見つけて返します。 現在の アプリケーション は、テンプレートコンテキストの上のアトリビュートとして指定されます。 アプリケーションは複数の配置を持つことを想定していて、テンプレートのレンダ リングをするために使われる ContextRequestContextcurrent_app アトリビュートに指定されます。

    現在のアプリケーションは reverse() 関数の引数から、手動で 指定することも出来ます。

  3. もし、現在のアプリケーションがないとしたらどうでしょう。 Django は デフォルトのアプリケーションインスタンスを探します。デフォルトの アプリケーションインスタンスは、アプリケーションの名前空間とマッチする インスタンスの名前空間を持つインスタンスです。(この例では、 myapp のインスタンスは myapp と呼ばれます)

  4. もし、デフォルトのアプリケーションインスタンスがなかったとしたら、 Django は一番初めに配置されたアプリケーションのインスタンスを選択します。 それは、インスタンスの名前がどんなものであってもそうでしょう。

  5. もし、提供された名前空間がステップの1のアプリケーションの名前空間と マッチしない場合、 Djangoはインスタンスの名前空間として、直接参照しようと します。

もし入れ子になった名前空間なら、ビューの名前が逆引きできるまで、名前空間の それぞれのパートに対してこれらのステップを繰り返します。

この行動の解決戦略をお見せしましょう、 myapp: の foo と呼ばれる インスタンスと、 bar と呼ばれるものについて考えてみましょう。 myapp はメインのインデックスページを持っていて、 URL の名前は index で す。セットアップを使って、参照可能にしてみましょう。:

  • もし、インスタンスのうち一つが現在のものであれば、言い換えると、もし bar インスタンスの中でユーティリティページをレンダリングしならば、 myapp:index は、 bar インスタンスのインデックスページとして 逆引きします。
  • もし、現在のインスタンスがなければ、言い換えると、もしサイトのどこかで ページのレンダリングを行うならば、 myapp:index は最後に登録された myapp のインスタンスを逆引きします。これらは通常のインスタンスではなく、 myapp の最後のインスタンスが使われます。これは foobar で、プロジェクトの URL パターンに導入された順番に依存します。
  • foo:index は常に foo インスタンスのインデックスページを解決しようと します。

もし、通常のインスタンスも存在すれば、すなわち、 myapp と名前づけられた インスタンスが存在すると、このようなことがおきます。:

  • もし、インスタンスのうち一つが現在のものであれば、言い換えると、もし bar インスタンスの中でユーティリティページをレンダリングしならば、 myapp:index は、 bar インスタンスのインデックスページとして 逆引きします。
  • もし、現在インスタンスがなければ、言い換えるとサイトのどこかのページを レンダリングするなら myapp:index は、通常のインスタンスの インデックスページとして逆引きします。
  • foo:index は、再び foo インスタンスのインデックスページへと 逆引きします。

django.core.urlresolvers ユーティリティ関数

reverse()

コード中で url のようなことをしたい場合のために、Django では django.core.urlresolvers.reverse モジュールを提供しています:

reverse(viewname[, urlconf=None, args=None, kwargs=None, current_app=None])

viewname は関数名 (関数への参照か、関数名の文字列表記で、 urlpatterns 上で使っている形式) または URL パターン名 です。通常、 urlconf パラメタについて考える必要はなく、以下のように、固定引数とキー ワード引数だけを指定して url マッチングを行います:

from django.core.urlresolvers import reverse

def myview(request):
    return HttpResponseRedirect(reverse('arch-summary', args=[1945]))

reverse() 関数は大抵の正規表現パターンを URL に逆変換できますが、全てと は限りません。今のところ、パターン中に垂直バー ("|") を含められません。 垂直バーを含むパターンは、 URL からビューへのマッチングには問題なく使えます が、パターンの逆変換はできないので注意してください。

current_app 引数は、リゾルバが現在実行しているるビューが属している アプリケーションを指し示すためのヒントを提供します。この current_app 引数は、アプリケーションの名前空間をひも解き、指定したアプリケーション インスタンスへと導くヒントとして扱われ、 URL 名前空間 に従っています。

args の代わりに、 kwargs を用いることもできます。例えば:

>>> reverse('admin:app_list', kwargs={'app_label': 'auth'})
'/admin/auth/'

argskwargs は、 reverse() を同時に通過することはできません。

ビューが全て正しいことを確認してください

URL 名の種々のパターンへのひも付けの生成の一部として、 reverse() 関数は、 URLconf ファイルのすべてと調べる各ビューの名前 をインポートする必要があります。これは各ビュー関数のインポートと関連 しています。もし 何か エラーが、ビュー関数のインポートする中で起きれば 、それは reverse() がエラーを返す原因になります。もし、ビュー関数が 逆引きしようとしたものでなかったときでさえもです。

URLconf ファイルの中でビューの参照が実在するのと、 正しくインポートされていることを確かにしてください。 参照するビューがまだ書かれていないのに、それを行に含まないでください。 なぜならそのビューはまだインポートできないからです。

Note

reverse() によって返される文字列は、 ref:URL クオート <uri-and-iri-handling> です。例えば:

>>> reverse('cities', args=[u'Orléans'])
'.../Orl%C3%A9ans/'

もっとエンコーディングを適用するには(urlquote()urllib.quote のように) reverse() のアウトプットは望ましくない 結果を引き起こします。

reverse_lazy()

Django 1.4 で新たに登場しました: リリースノートを参照してください

reverse() の簡単に使えるバージョン

reverse_lazy(viewname[, urlconf=None, args=None, kwargs=None, current_app=None])

これは、プロジェクトの URLConf がロードされる前に、 URL 逆引きを使う必要がある 場合に便利です。いくつかの一般的なケースではこの関数がまさに必要になります:

  • ジェネリッククラスベースビューをの url アトリビュートとして、 URL を逆引きして提供する場合
  • デコレータとして、逆引き URL を提供する場合( django.contrib.auth.decorators.permission_required() の デコレータのための login_url 引数のような)
  • 関数のシグネチャの中で、パラメータとしてデフォルトの値として 逆引きした URL を提供する場合。

resolve()

django.core.urlresolvers.resolve() 関数は、URL のパスとそれに付随してい るビュー関数を呼び出すのに使われます。

resolve(path, urlconf=None)

path はあなたがひも解きたい URL パスです。 reverse() と一緒で、 urlconf パラメータ に関して考える必要はありません。この関数が返すのは ResolverMatch オブジェクトで、これは解決された URL の様々なメタデータにアクセスできる クラスです。

もし、 URL がひも解かれなかったら、関数は Http404 という例外を発生させます。

class ResolverMatch
func

URL を提供するのに使われるビュー関数です。

args

これは、ビュー関数に渡されて、 URL からパースされた 引数です。

kwargs

このキーワード引数はビュー関数に渡され、 URL からパースされた 引数です。

url_name

URL にマッチした URL パターンの名前です。

app_name

アプリケーションの名前空間で、 URL にマッチした URL パターンの 為に使われます。

namespace

インスタンスの名前空間で、 URL にマッチした URL パターンの 為に使われます。

namespaces

インスタンスのフルの名前空間の、個別の名前空間の要素を リストにしたもので、 URL パターンにマッチした URL のために 用いられます。すなわち、もし名前空間が foo:bar であるなら、 このリストは ['foo', 'bar'] になります。

ResolverMatch オブジェクトは、 URL にマッチする URL パターンに ついての情報を提供し、それの問い合わせを行うことが出来ます。:

# Resolve a URL
match = resolve('/some/path/')
# Print the URL pattern that matches the URL
print match.url_name

ResolverMatch オブジェクトは、三つのものに対して割当てられます。:

func, args, kwargs = resolve('/some/path/')
Django 1.3 で変更されました: 三つの割当は、逆方向への互換性のためにあります。 resolve() は Django 1.3 では、 三つのものを含んで(ビュー関数と、引数、キーワード引数)いて、 ResolverMatch object (名前空間とパターン情報の提供も同じように) は DJango の前バージョンのものでは使えません。

一つの resolve() の使い方としては、 Http404 エラーが出ているかどうかを、リダイレクトする前にテストする ような用途です。:

from urlparse import urlparse
from django.core.urlresolvers import resolve
from django.http import HttpResponseRedirect, Http404

def myview(request):
    next = request.META.get('HTTP_REFERER', None) or '/'
    response = HttpResponseRedirect(next)

    #リクエストとレスポンスを必要に合わせて変更してください。
    #依存するローカルな環境のクッキーもセットしてください。

    view, args, kwargs = resolve(urlparse(next)[2])
    kwargs['request'] = request
    try:
        view(*args, **kwargs)
    except Http404:
        return HttpResponseRedirect('/')
    return response

get_script_prefix()

get_script_prefix()

通常、 reverse() を 使うか、 permalink() を URL を アプリケーション内で定義するために用います。しかし、もしアプリケーションが 自身の URL の階層の一部分を構成するのならば、 URL を生成する機会が必要です。 このようなケースで、 Web サーバー内の Django プロジェクトの ベース URL を 見つけられる必要があり(通常、 reverse() がこのような必要性を満たしてくれます)、この場合、 get_script_prefix() を呼ぶと、Django プロジェクトにへ URL スクリプトのプレフィクスを返します。 もし、 Django プロジェクトが Web サーバーのルートに存在するなら、 これは常に "/" になります、しかしこれは変更可能です、 django.root を使うことでインスタンスで出来ます。( Django と Apache と mod_python を見てください。)