.. _topics-http-urls: ================== URL ディスパッチャ ================== :revision-up-to: 17812 (1.4) .. module:: django.core.urlresolvers すっきりした、簡潔で明解な URL スキームの設計は、高品質の Web アプリケーショ ンでは重要な要素です。 Django では、フレームワークの制限なしに、望み通りの URL を設計できます。 ``.php`` や ``.cgi`` といった拡張子は必要なく、 ``0,2097,1-1-1928,00`` のよ うな意味不明の URL にする必要もありません。 URL はすっきりした扱いやすいものにすべきであるという主張については、ワール ドワイドウェブの産みの親である Tim Berners-Lee の優れた解説、 `Cool URIs don't change`_ を参照してください。 .. _Cool URIs don't change: http://www.w3.org/Provider/Style/URI 概要 ==== あるアプリケーション向けの URL を設計するには、 **URLconf** (URL 設定: URL configuration) と呼びならわされている Python モジュールを作成します。このモ ジュールは pure Python のコードで、中にはただ URL パターン (単純な正規表現) から Python のコールバック関数 (自作のビュー) へのマッピングが入っているだ けです。 .. versionadded:: 1.4 Django はまた、 URL が稼働している言語から翻訳することを許可しています。 このプロセスは、 :ref:`internationalization docs ` で、説明 しています。 このマッピングは短くもできますし、必要なだけ長くもできます。他のマッピング も参照できます。また、 pure Python コードなので、動的に生成できます。 .. _how-django-processes-a-request: Django のリクエスト処理 ======================= ユーザが Django で作られたサイト上のページをリクエストした時に、どの Python コードが実行されるかは以下のアルゴリズムで決定されます: 1. まず、Django は、どのモジュールをルート URLconf として使うか決定しま す。もともとは、この値は ``ROOT_URLCONF`` に設定されています。ただし、 ``HttpRequest`` オブジェクトに ``urlconf`` という属性が設定されてい た場合( :ref:`request processing ` で設定されます) 、その値を ``ROOT_URLCONF`` の代わりに使います。 2. Django は上記の Python モジュールをロードして、 ``urlpatterns`` とい う名前の変数を探します。この変数の値は Python のリストで、 :func:`django.conf.urls.patterns` が返すのと同じ形式です。 3. Django は URL パターンを順に調べて、リクエスト URL に最初にマッチし たところで止まります。 4. 何らかの正規表現にマッチしたら、 Django はマッピングされているビュー を import して呼び出します。ビューは単純な Python 関数です。ビュー関 数の第一引数には :class:`~django.http.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')`` を呼び出し ます。 .. _Dive Into Python's explanation: http://diveintopython.net/regular_expressions/street_addresses.html#re.matching.2.3 名前つきグループ ================ 上の例では、 *名前なしの* 簡単な正規表現グループを (丸括弧表記で) 使って URL から情報を取り出し、ビュー関数に *固定引数* として渡していました。より 高度な方法に、 *名前つきの* 正規表現グループで URL から情報を取り出し、ビュー の *キーワード引数* に渡すものがあります。 Python の正規表現では、名前つき正規表現グループは、 ``name`` をグループの名 前、 ``pattern`` をマッチさせるパターンとして、 ``(?Ppattern)`` で表 されます。 上の URLconf の例を書き換えて、名前つきグループにしたものを示します:: urlpatterns = patterns('', (r'^articles/2003/$', 'news.views.special_case_2003'), (r'^articles/(?P\d{4})/$', 'news.views.year_archive'), (r'^articles/(?P\d{4})/(?P\d{2})/$', 'news.views.month_archive'), (r'^articles/(?P\d{4})/(?P\d{2})/(?P\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`` の書き方 ========================= ``urlpatterns`` は :func:`django.conf.urls.patterns`` の返す形式の Python リストになります。 ``urlpatterns`` 変数の値を作るときには、常に ``patterns()`` を使うようにして下さい。 ``django.conf.urls`` 汎用的な関数 ================================= .. module:: django.conf.urls .. deprecated:: 1.4 Django 1.4 の関数 ``patterns``, ``url``, ``include`` に加えて ``handler*`` は ``django.conf.urls`` モジュールの中にあり、以下で説明さ れているシンボル群です。 Django 1.3 までは、これらは ``django.conf.urls.defaults`` の中に位置していました。まだ、以前のモジュールからインポート することが出来ますが、 Django 1.6 でそれが出来なくなります。 patterns -------- .. function:: 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 --- .. function:: 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 ------- .. function:: include() 関数は現在の URLconf で "included" しておくべき Python のフル import パス を他の URLconf モジュールへと 取りこみます。 :func:`include` も引数としてイテレート可能です。これは、 URL パターンを返します。 `他の URLconf を取り込む`_ を見てください。 エラーハンドリング ================== Django が、リクエストされた URL にマッチする正規表現を 見つけられなかったとき、または例外が発生したとき、 Django は error-handling view を発生させます。ビューはルートの URlconf に設定された三つの変数で、指定されたケースで使用 されます。これらの変数の設定は、他のどの URLconf にも影響を 与えません。 :ref:`エラービューのカスタマイズ ` を参照してください、もっと詳しいことが載っています。 handler403 ---------- .. data:: handler403 呼ぶことができます、またはユーザがリソースにアクセスするのに 必要なパーミッション(permission 権限)を持っていない場合に、 ビュー関数への完全な Python の import パスが入った文字列です。 通常、これは ``'django.views.defaults.permission_denied'`` これのデフォルト値は満足させるでしょう。 :ref:`403 (閲覧が禁止されています ビュー) ` にもっと沢山の情報が載っています。 .. versionadded:: 1.4 ``handler403`` は Django 1.4の新しいものです handler404 ---------- .. data:: handler404 呼び出せるか、マッチする URL パターンがない場合に呼び出されるビュー関数への、 完全な Python の import パスが入った文字列です。 デフォルト値は、 ``'django.views.defaults.page_not_found'`` です。 普通はこのデフォルト値で十分のはずです。 .. versionchanged:: 1.2 前のバージョンの Django では、 import パスが入った文字列のみを、受け取れ ます。 handler500 ---------- .. data:: handler500 呼び出しか、サーバエラーが生じた場合に呼び出されるビュー関数への、 完全な Python の import パスが入った文字列です。 サーバエラーはビュー関数のコード中で実行時エラーが生じたときに起きます。 デフォルト値は、 ``'django.views.defaults.page_not_found'`` です。 普通はこのデフォルト値で十分のはずです。 .. versionchanged:: 1.2 前のバージョンの Django では、 import パスが入った文字列のみを、受け取れ ます。 URL 中のテキストを取り出す際の注意 ================================== 引数として取り出したテキストは、正規表現が何にマッチするかに関係なく通常の Python 文字列型になります。例えば、下のような URLconf の行:: (r'^articles/(?P\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\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()`` 呼び出しの中で共通 のプレフィクスを指定できます。 :doc:`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\d{4})/(?P[a-z]{3})/$', 'django.views.generic.date_based.archive_month'), (r'^tag/(?P\w+)/$', 'weblog.views.tag'), ) は、以下のような書き方に改められます:: from django.conf.urls import patterns, url, include urlpatterns = patterns('django.views.generic.date_based', (r'^$', 'archive_index'), (r'^(?P\d{4})/(?P[a-z]{3})/$','archive_month'), ) urlpatterns += patterns('weblog.views', (r'^tag/(?P\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\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 のアドミンは、 :class:`~django.contrib.admin.AdminSite` のインスタンスとして 配置されます。それぞれの `~django.contrib.admin.AdminSite` インスタンスは ``urls`` アトリビュートを持っていて、 それらは url パターンとしてインスタンスに使用可能です。 それは、アドミンのインターフェイスを配置する時に、 ``include()`` を プロジェクトの ``urlpatterns`` に入れることができます。 .. _`Django Web site`: https://www.djangoproject.com/ .. _`Django ウェブサイト`: `Django Web site`_ キャプチャされたパラメタ ------------------------ include された側の URLconf は、親となる URLconf で取り出された全てのパラメ タを受け継ぎます。従って、以下のような例はうまく動作します:: # In settings/urls/main.py urlpatterns = patterns('', (r'^(?P\w+)/blog/', include('foo.urls.blog')), ) # In foo/urls/blog.py urlpatterns = patterns('foo.views', (r'^$', 'blog.index'), (r'^archive/$', 'blog.archive'), ) 上の例では、 include された側にも ``"username"`` 変数が期待どおりに渡されま す。 .. _topics-http-defining-url-namespaces: URL の名前空間を定義する ------------------------ もし、複数のインスタンスを一つのアプリケーションで必要としたならば、 インスタンスの間で区別を付けられることが役立つでしょう。 これは、一つのアプリケーションが分割する URL の名前付けの 複数のインスタンスにおいて :ref:`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()`` することもできます:: (, , ) これは、与えられたアプリケーションとインスタンスの名前空間へと指定された URL パターンを含みます。例えば、 Django の :class:`AdminSite` オブジェクトの ``urls`` アトリビュートは 3つのタプルを返し、それはアドミンサイトの 全てのパターンを含んでいます。そして、アドミンインスタンスの名前を足すと アプリケーション名前空間の ``admin`` です。 一度定義した、名前空間化された URL は、名前空間から逆引きしてたどること が出来ます。もっと詳しく、名前空間づけた URL を逆引きする方法について知るには、 :ref:`URL 名前空間 ` を見てください。 ビュー関数に追加のオプションを渡す ================================== URLconf には、ビュー関数に追加の引数を Python の辞書型で渡せるようにするた めのフックがあります。 URLconf タプルにはオプションとして 3 つめの要素を指定できます。この要素は ビューに渡したい追加の引数からなる辞書にします。 例えば:: urlpatterns = patterns('blog.views', (r'^blog/(?P\d{4})/$', 'year_archive', {'foo': 'bar'}), ) この例では、 ``/blog/2005/`` というリクエストに対し、 Django は ``blog.views.year_archive()`` ビューを呼び出し、以下のキーワード引数を渡し ます:: year='2005', foo='bar' このテクニックは :doc:`汎用ビュー ` や :doc:`配信フィードフレームワーク ` で、メタデータ やビューへのオプションを渡すために使われています。 .. admonition:: 衝突を避ける 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), ) どのスタイルを使うかは自由です。 このテクニックを使った場合 (文字列の代わりにオブジェクトを渡した場合) 上で説明した ""ビュープレフィクス"" は効果を及ぼさないので注意してください。 .. _naming-url-patterns: URL パターンに名前を付ける ========================== URLconf 中の複数の URL パターンから同じビュー関数を呼ぶケースはよくあります。 たとえば、以下の二つの URL パターンは、どちらも ``archive`` というビューを 指しています:: urlpatterns = patterns('', (r'/archive/(\d{4})/$', archive), (r'/archive-summary/(\d{4})/$', archive, {'summary': True}), ) この URLconf には何ら問題はないのですが、 (``permalink()`` デコレータや :ttag:`{% 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 にアクセスすることができます。 .. code-block:: html+django {% url arch-summary 1945 %} {% url full-archive 2007 %} つまり、二つの URL パターンがどちらも同じく ``archive`` ビューを参照してい ても、 ``url()`` に ``name`` パラメタを指定すれば、テンプレート中で二つを区 別できるというわけです。 URLconf エントリに付ける名前は、どんな文字を入れても構いません。 Python の 変数名規則には縛られません。 .. note:: URLconf エントリに名前を付ける場合、他のアプリケーションの名前と衝突し なさそうな名前を使ってください。例えば、ある URL パターンを "*comment*" と命名していて、他のアプリケーションでも同じ名前を使っていたとしましょ う。この名前をテンプレートで使うと、もはやどちらの URL がテンプレートに 挿入されるのか判断する術はありません。 URLconf エントリの名前に、例えばアプリケーション名などからとったプレフィ クスを追加しておけば、名前が衝突しにくくなってよいでしょう。というわけ で、単に "*comment*" ではなく、 "*myapp-comment*" にするよう勧めます。 .. _topics-http-reversing-url-namespaces: URL 名前空間 -------------- 名前空間化された URL は ``:`` 演算子を使うことによって指定されます。 例えば、アドミンアプリケーションの、メインのインデックスページは ``admin:index`` を使うことによって参照されます。 名前空間は、ネスト(nest 入れ子)することができます。 ``foo:bar:whiz`` と名前づけられた URL は、トップレベルの名前空間である ``foo`` の中から ``bar`` という名前で定義されたものを探し、さらにその中から ``whiz`` という名前のパターンを探します。 名前空間化された URL (すなわち、``myapp:index`` のようなもの) が与えられる て解決すると、 Django は完全にパス化されたものをパーツごとに分解しようとしま す。そしてその時に、 URL の探索を行おうとします。 1. 最初に、 Django はアプリケーションの名前空間とマッチするものを探そうとし ます。(この例では ``myapp`` です。)これは、アプリケーションのインスタンスの リストを作ります。 2. もし、 *現在の* アプリケーションが定義されていれば、 Django は インスタンスの為に URL リゾルバを見つけて返します。 *現在の* アプリケーション は、テンプレートコンテキストの上のアトリビュートとして指定されます。 アプリケーションは複数の配置を持つことを想定していて、テンプレートのレンダ リングをするために使われる ``Context`` か ``RequestContext`` の ``current_app`` アトリビュートに指定されます。 現在のアプリケーションは :func:`reverse()` 関数の引数から、手動で 指定することも出来ます。 3. もし、現在のアプリケーションがないとしたらどうでしょう。 Django は デフォルトのアプリケーションインスタンスを探します。デフォルトの アプリケーションインスタンスは、アプリケーションの名前空間とマッチする インスタンスの名前空間を持つインスタンスです。(この例では、 ``myapp`` のインスタンスは ``myapp`` と呼ばれます) 4. もし、デフォルトのアプリケーションインスタンスがなかったとしたら、 Django は一番初めに配置されたアプリケーションのインスタンスを選択します。 それは、インスタンスの名前がどんなものであってもそうでしょう。 5. もし、提供された名前空間がステップの1のアプリケーションの名前空間と マッチしない場合、 Djangoはインスタンスの名前空間として、直接参照しようと します。 もし入れ子になった名前空間なら、ビューの名前が逆引きできるまで、名前空間の それぞれのパートに対してこれらのステップを繰り返します。 この行動の解決戦略をお見せしましょう、 ``myapp``: の ``foo`` と呼ばれる インスタンスと、 ``bar`` と呼ばれるものについて考えてみましょう。 ``myapp`` はメインのインデックスページを持っていて、 URL の名前は `index` で す。セットアップを使って、参照可能にしてみましょう。: * もし、インスタンスのうち一つが現在のものであれば、言い換えると、もし ``bar`` インスタンスの中でユーティリティページをレンダリングしならば、 ``myapp:index`` は、 ``bar`` インスタンスのインデックスページとして 逆引きします。 * もし、現在のインスタンスがなければ、言い換えると、もしサイトのどこかで ページのレンダリングを行うならば、 ``myapp:index`` は最後に登録された ``myapp`` のインスタンスを逆引きします。これらは通常のインスタンスではなく、 ``myapp`` の最後のインスタンスが使われます。これは ``foo`` か ``bar`` で、プロジェクトの URL パターンに導入された順番に依存します。 * ``foo:index`` は常に ``foo`` インスタンスのインデックスページを解決しようと します。 もし、通常のインスタンスも存在すれば、すなわち、 `myapp` と名前づけられた インスタンスが存在すると、このようなことがおきます。: * もし、インスタンスのうち一つが現在のものであれば、言い換えると、もし ``bar`` インスタンスの中でユーティリティページをレンダリングしならば、 ``myapp:index`` は、 ``bar`` インスタンスのインデックスページとして 逆引きします。 * もし、現在インスタンスがなければ、言い換えるとサイトのどこかのページを レンダリングするなら ``myapp:index`` は、通常のインスタンスの インデックスページとして逆引きします。 * ``foo:index`` は、再び ``foo`` インスタンスのインデックスページへと 逆引きします。 ``django.core.urlresolvers`` ユーティリティ関数 =============================================== .. currentmodule:: django.core.urlresolvers reverse() --------- コード中で :ttag:`url` のようなことをしたい場合のために、Django では :mod:`django.core.urlresolvers.reverse` モジュールを提供しています: .. function:: 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])) .. _URL パターン名: `Naming URL patterns`_ ``reverse()`` 関数は大抵の正規表現パターンを URL に逆変換できますが、全てと は限りません。今のところ、パターン中に垂直バー (``"|"``) を含められません。 垂直バーを含むパターンは、 URL からビューへのマッチングには問題なく使えます が、パターンの逆変換はできないので注意してください。 ``current_app`` 引数は、リゾルバが現在実行しているるビューが属している アプリケーションを指し示すためのヒントを提供します。この ``current_app`` 引数は、アプリケーションの名前空間をひも解き、指定したアプリケーション インスタンスへと導くヒントとして扱われ、 :ref:`URL 名前空間 ` に従っています。 ``args`` の代わりに、 ``kwargs`` を用いることもできます。例えば:: >>> reverse('admin:app_list', kwargs={'app_label': 'auth'}) '/admin/auth/' ``args`` と ``kwargs`` は、 ``reverse()`` を同時に通過することはできません。 .. admonition:: ビューが全て正しいことを確認してください URL 名の種々のパターンへのひも付けの生成の一部として、 ``reverse()`` 関数は、 URLconf ファイルのすべてと調べる各ビューの名前 をインポートする必要があります。これは各ビュー関数のインポートと関連 しています。もし *何か* エラーが、ビュー関数のインポートする中で起きれば 、それは ``reverse()`` がエラーを返す原因になります。もし、ビュー関数が 逆引きしようとしたものでなかったときでさえもです。 URLconf ファイルの中でビューの参照が実在するのと、 正しくインポートされていることを確かにしてください。 参照するビューがまだ書かれていないのに、それを行に含まないでください。 なぜならそのビューはまだインポートできないからです。 .. note:: :meth:`~django.core.urlresolvers.reverse` によって返される文字列は、 ref:`URL クオート ` です。例えば:: >>> reverse('cities', args=[u'Orléans']) '.../Orl%C3%A9ans/' もっとエンコーディングを適用するには(:meth:`~django.utils.http.urlquote` か ``urllib.quote`` のように) :meth:`~django.core.urlresolvers.reverse` のアウトプットは望ましくない 結果を引き起こします。 reverse_lazy() -------------- .. versionadded:: 1.4 `reverse()`_ の簡単に使えるバージョン .. function:: reverse_lazy(viewname, [urlconf=None, args=None, kwargs=None, current_app=None]) これは、プロジェクトの URLConf がロードされる前に、 URL 逆引きを使う必要がある 場合に便利です。いくつかの一般的なケースではこの関数がまさに必要になります: * ジェネリッククラスベースビューをの ``url`` アトリビュートとして、 URL を逆引きして提供する場合 * デコレータとして、逆引き URL を提供する場合( :func:`django.contrib.auth.decorators.permission_required` の デコレータのための ``login_url`` 引数のような) * 関数のシグネチャの中で、パラメータとしてデフォルトの値として 逆引きした URL を提供する場合。 resolve() --------- :func:`django.core.urlresolvers.resolve` 関数は、URL のパスとそれに付随してい るビュー関数を呼び出すのに使われます。 .. function:: resolve(path, urlconf=None) ``path`` はあなたがひも解きたい URL パスです。 :func:`~django.core.urlresolvers.reverse` と一緒で、 ``urlconf`` パラメータ に関して考える必要はありません。この関数が返すのは :class:`ResolverMatch` オブジェクトで、これは解決された URL の様々なメタデータにアクセスできる クラスです。 もし、 URL がひも解かれなかったら、関数は :class:`~django.http.Http404` という例外を発生させます。 .. class:: ResolverMatch .. attribute:: ResolverMatch.func URL を提供するのに使われるビュー関数です。 .. attribute:: ResolverMatch.args これは、ビュー関数に渡されて、 URL からパースされた 引数です。 .. attribute:: ResolverMatch.kwargs このキーワード引数はビュー関数に渡され、 URL からパースされた 引数です。 .. attribute:: ResolverMatch.url_name URL にマッチした URL パターンの名前です。 .. attribute:: ResolverMatch.app_name アプリケーションの名前空間で、 URL にマッチした URL パターンの 為に使われます。 .. attribute:: ResolverMatch.namespace インスタンスの名前空間で、 URL にマッチした URL パターンの 為に使われます。 .. attribute:: ResolverMatch.namespaces インスタンスのフルの名前空間の、個別の名前空間の要素を リストにしたもので、 URL パターンにマッチした URL のために 用いられます。すなわち、もし名前空間が ``foo:bar`` であるなら、 このリストは ``['foo', 'bar']`` になります。 :class:`ResolverMatch` オブジェクトは、 URL にマッチする URL パターンに ついての情報を提供し、それの問い合わせを行うことが出来ます。:: # Resolve a URL match = resolve('/some/path/') # Print the URL pattern that matches the URL print match.url_name :class:`ResolverMatch` オブジェクトは、三つのものに対して割当てられます。:: func, args, kwargs = resolve('/some/path/') .. versionchanged:: 1.3 三つの割当は、逆方向への互換性のためにあります。 :func:`~django.core.urlresolvers.resolve` は Django 1.3 では、 三つのものを含んで(ビュー関数と、引数、キーワード引数)いて、 :class:`ResolverMatch` object (名前空間とパターン情報の提供も同じように) は DJango の前バージョンのものでは使えません。 一つの :func:`~django.core.urlresolvers.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 permalink() ----------- :func:`django.db.models.permalink` は、モデルの ``get_absolute_url()`` メソッ ドのような、完全な URL パスを返す短いメソッドを書く際に便利なデコレータです。 詳細は、 :func:`django.db.models.permalink` を参照してください。 get_script_prefix() ------------------- .. function:: get_script_prefix() 通常、 :func:`~django.core.urlresolvers.reverse` を 使うか、 :func:`~django.db.models.permalink` を URL を アプリケーション内で定義するために用います。しかし、もしアプリケーションが 自身の URL の階層の一部分を構成するのならば、 URL を生成する機会が必要です。 このようなケースで、 Web サーバー内の Django プロジェクトの ベース URL を 見つけられる必要があり(通常、 :func:`~django.core.urlresolvers.reverse` がこのような必要性を満たしてくれます)、この場合、 ``get_script_prefix()`` を呼ぶと、Django プロジェクトにへ URL スクリプトのプレフィクスを返します。 もし、 Django プロジェクトが Web サーバーのルートに存在するなら、 これは常に ``"/"`` になります、しかしこれは変更可能です、 ``django.root`` を使うことでインスタンスで出来ます。( :doc:`Django と Apache と mod_python ` を見てください。)