URLディスパッチャー
クリーンでエレガントなURLスキームは、高品質のWebアプリケーションの重要な詳細です。 Djangoを使用すると、フレームワークの制限なしに、必要に応じてURLを設計できます。
URLがクリーンで使用可能である必要がある理由に関する優れた議論については、World WideWebの作成者であるTimBerners-Leeによる Cool URIs not change を参照してください。
概要
アプリのURLを設計するには、 URLconf (URL構成)と非公式に呼ばれるPythonモジュールを作成します。 このモジュールは純粋なPythonコードであり、URLパス式からPython関数(ビュー)へのマッピングです。
このマッピングは、必要に応じて短くすることも長くすることもできます。 他のマッピングを参照できます。 また、純粋なPythonコードであるため、動的に構築できます。
Djangoは、アクティブな言語に従ってURLを翻訳する方法も提供します。 詳細については、国際化ドキュメントを参照してください。
Djangoがリクエストを処理する方法
ユーザーがDjangoを利用したサイトからページをリクエストすると、これはシステムが実行するPythonコードを決定するために従うアルゴリズムです。
- Djangoは、使用するルートURLconfモジュールを決定します。 通常、これは:setting: `ROOT_URLCONF` 設定の値ですが、着信
HttpRequest
オブジェクトに urlconf 属性(ミドルウェアによって設定)がある場合、 :setting: `ROOT_URLCONF` 設定の代わりに値が使用されます。 - DjangoはそのPythonモジュールをロードし、変数
urlpatterns
を探します。 これは、 django.urls.path()および/または django.urls.re_path()インスタンスのシーケンスである必要があります。 - Djangoは各URLパターンを順番に実行し、 path_info と照合して、要求されたURLに一致する最初のパターンで停止します。
- URLパターンの1つが一致すると、Djangoは指定されたビューをインポートして呼び出します。これはPython関数(またはクラスベースのビュー)です。 ビューには次の引数が渡されます。
- HttpRequest のインスタンス。
- 一致したURLパターンに名前付きグループが含まれていない場合、正規表現からの一致が位置引数として提供されます。
- キーワード引数は、提供されたパス式と一致する名前付き部分で構成され、オプションの
kwargs
引数で django.urls.path()または[ X210X] django.urls.re_path()。
- 一致するURLパターンがない場合、またはこのプロセスのいずれかの時点で例外が発生した場合、Djangoは適切なエラー処理ビューを呼び出します。 以下のエラー処理を参照してください。
例
URLconfのサンプルは次のとおりです。
from django.urls import path
from . import views
urlpatterns = [
path('articles/2003/', views.special_case_2003),
path('articles/<int:year>/', views.year_archive),
path('articles/<int:year>/<int:month>/', views.month_archive),
path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail),
]
ノート:
- URLから値を取得するには、山かっこを使用します。
- キャプチャされた値には、オプションでコンバータタイプを含めることができます。 たとえば、
<int:name>
を使用して整数パラメーターをキャプチャします。 コンバーターが含まれていない場合、/
文字を除くすべての文字列が一致します。 - すべてのURLにスラッシュがあるため、先頭にスラッシュを追加する必要はありません。 たとえば、
/articles
ではなく、articles
です。
リクエストの例:
/articles/2005/03/
へのリクエストは、リストの3番目のエントリと一致します。 Djangoは関数views.month_archive(request, year=2005, month=3)
を呼び出します。/articles/2003/
は、2番目のパターンではなく、リストの最初のパターンと一致します。これは、パターンが順番にテストされ、最初のパターンが最初に合格するテストであるためです。 このような特殊なケースを挿入するために、順序を自由に利用してください。 ここで、Djangoは関数views.special_case_2003(request)
を呼び出します。/articles/2003
は、これらのパターンのいずれにも一致しません。これは、各パターンでURLがスラッシュで終わる必要があるためです。/articles/2003/03/building-a-django-site/
は最終的なパターンと一致します。 Djangoは関数views.article_detail(request, year=2003, month=3, slug="building-a-django-site")
を呼び出します。
パスコンバーター
デフォルトでは、次のパスコンバータを使用できます。
str
-パス区切り文字'/'
を除く、空でない文字列に一致します。 コンバーターが式に含まれていない場合、これがデフォルトです。int
-ゼロまたは任意の正の整数に一致します。int
を返します。slug
-ASCII文字または数字に加えて、ハイフンとアンダースコア文字で構成されるすべてのスラッグ文字列に一致します。 たとえば、building-your-1st-django-site
です。uuid
-フォーマットされたUUIDに一致します。 複数のURLが同じページにマッピングされないようにするには、ダッシュを含め、文字を小文字にする必要があります。 たとえば、075194d3-6885-417e-a8a8-6c931e272f00
です。UUID
インスタンスを返します。path
-パス区切り文字'/'
を含む、空でない文字列に一致します。 これにより、str
のようにURLパスのセグメントではなく、完全なURLパスと照合できます。
カスタムパスコンバーターの登録
より複雑なマッチング要件については、独自のパスコンバーターを定義できます。
コンバーターは、以下を含むクラスです。
文字列としての
regex
クラス属性。to_python(self, value)
メソッド。一致した文字列を、ビュー関数に渡す必要のある型に変換します。 指定された値を変換できない場合は、ValueError
を上げる必要があります。ValueError
は一致しないと解釈され、その結果、別のURLパターンが一致しない限り、404応答がユーザーに送信されます。to_url(self, value)
メソッド。Pythonタイプを、URLで使用される文字列に変換します。 指定された値を変換できない場合は、ValueError
を上げる必要があります。ValueError
は一致しないと解釈され、その結果、別のURLパターンが一致しない限り、 reverse()は NoReverseMatch を発生させます。バージョン3.1で変更:一致が追加されなかったことを示すために
ValueError
を上げるためのサポート。
例えば:
class FourDigitYearConverter:
regex = '[0-9]{4}'
def to_python(self, value):
return int(value)
def to_url(self, value):
return '%04d' % value
register_converter()を使用して、URLconfにカスタムコンバータークラスを登録します。
from django.urls import path, register_converter
from . import converters, views
register_converter(converters.FourDigitYearConverter, 'yyyy')
urlpatterns = [
path('articles/2003/', views.special_case_2003),
path('articles/<yyyy:year>/', views.year_archive),
...
]
正規表現の使用
パスとコンバーターの構文がURLパターンを定義するのに十分でない場合は、正規表現を使用することもできます。 これを行うには、 path()の代わりに re_path()を使用します。
Python正規表現では、名前付き正規表現グループの構文は(?P<name>pattern)
です。ここで、name
はグループの名前であり、pattern
は一致するパターンです。
正規表現を使用して書き直された、以前のURLconfの例を次に示します。
from django.urls import path, re_path
from . import views
urlpatterns = [
path('articles/2003/', views.special_case_2003),
re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<slug>[\w-]+)/$', views.article_detail),
]
これにより、次の点を除いて、前の例とほぼ同じことが実現します。
- 一致する正確なURLは、わずかに制限されています。 たとえば、年の整数は正確に4桁の長さに制限されているため、10000年は一致しなくなります。
- キャプチャされた各引数は、正規表現がどのような種類の一致を行うかに関係なく、文字列としてビューに送信されます。
path()から re_path()に、またはその逆に切り替える場合、ビュー引数のタイプが変更される可能性があることに注意することが特に重要です。そのため、適応する必要がある場合があります。あなたの意見。
名前のない正規表現グループの使用
名前付きグループの構文と同様に、例えば (?P<year>[0-9]{4})
、名前のない短いグループを使用することもできます。 ([0-9]{4})
。
この使用法は、一致の意図された意味とビューの引数の間に誤ってエラーを導入しやすくなるため、特に推奨されません。
いずれの場合も、特定の正規表現内で1つのスタイルのみを使用することをお勧めします。 両方のスタイルが混在している場合、名前のないグループはすべて無視され、名前の付いたグループのみがビュー関数に渡されます。
ネストされた引数
正規表現はネストされた引数を許可し、Djangoはそれらを解決してビューに渡します。 逆にすると、Djangoは、ネストされたキャプチャされた引数を無視して、すべての外側のキャプチャされた引数を入力しようとします。 オプションでページ引数を取る次のURLパターンを検討してください。
from django.urls import re_path
urlpatterns = [
re_path(r'^blog/(page-(\d+)/)?$', blog_articles), # bad
re_path(r'^comments/(?:page-(?P<page_number>\d+)/)?$', comments), # good
]
どちらのパターンもネストされた引数を使用して解決します。たとえば、blog/page-2/
は、page-2/
と2
の2つの位置引数を持つblog_articles
と一致します。 comments
の2番目のパターンは、キーワード引数page_number
が2に設定されたcomments/page-2/
と一致します。 この場合の外側の引数は、キャプチャしない引数(?:...)
です。
blog_articles
ビューでは、最も外側のキャプチャされた引数を逆にする必要があります。この場合、page-2/
または引数なしで、comments
は、引数なしまたは[X185Xの値]で逆にすることができます。 ] 。
ネストされたキャプチャされた引数は、blog_articles
で示されるように、ビュー引数とURLの間に強い結合を作成します。ビューは、ビューが関心のある値だけでなく、URLの一部(page-2/
)を受け取ります。 ビューを反転するには、ページ番号の代わりにURLの一部を渡す必要があるため、この結合は反転時にさらに顕著になります。
経験則として、正規表現に引数が必要であるがビューがそれを無視する場合にのみ、ビューが処理する必要のある値をキャプチャし、キャプチャしない引数を使用します。
URLconfが検索する対象
URLconfは、通常のPython文字列として、要求されたURLを検索します。 これには、GETまたはPOSTパラメーター、あるいはドメイン名は含まれません。
たとえば、https://www.example.com/myapp/
へのリクエストでは、URLconfはmyapp/
を検索します。
https://www.example.com/myapp/?page=3
へのリクエストで、URLconfはmyapp/
を検索します。
URLconfはrequestメソッドを調べません。 つまり、すべてのリクエストメソッド– POST
、GET
、HEAD
など。 –同じURLの同じ関数にルーティングされます。
ビュー引数のデフォルトの指定
便利なトリックは、ビューの引数にデフォルトのパラメータを指定することです。 URLconfとビューの例を次に示します。
# URLconf
from django.urls import path
from . import views
urlpatterns = [
path('blog/', views.page),
path('blog/page<int:num>/', views.page),
]
# View (in blog/views.py)
def page(request, num=1):
# Output the appropriate page of blog entries, according to num.
...
上記の例では、両方のURLパターンが同じビュー(views.page
)を指していますが、最初のパターンはURLから何もキャプチャしません。 最初のパターンが一致する場合、page()
関数は、num
、1
のデフォルト引数を使用します。 2番目のパターンが一致する場合、page()
はキャプチャされたnum
値を使用します。
パフォーマンス
urlpatterns
の各正規表現は、最初にアクセスされたときにコンパイルされます。 これにより、システムが非常に高速になります。
エラー処理
Djangoが要求されたURLに一致するものを見つけられない場合、または例外が発生した場合、Djangoはエラー処理ビューを呼び出します。
これらの場合に使用するビューは、4つの変数によって指定されます。 ほとんどのプロジェクトではデフォルト値で十分ですが、デフォルト値をオーバーライドすることでさらにカスタマイズすることができます。
詳細については、エラービューのカスタマイズに関するドキュメントを参照してください。
このような値は、ルートURLconfで設定できます。 これらの変数を他のURLconfに設定しても、効果はありません。
値は呼び出し可能であるか、手元のエラー状態を処理するために呼び出される必要があるビューへの完全なPythonインポートパスを表す文字列である必要があります。
変数は次のとおりです。
handler400
– django.conf.urls.handler400 を参照してください。handler403
– django.conf.urls.handler403 を参照してください。handler404
– django.conf.urls.handler404 を参照してください。handler500
– django.conf.urls.handler500 を参照してください。
他のURLconfを含む
urlpatterns
はいつでも、他のURLconfモジュールを「含める」ことができます。 これは基本的に、URLのセットを他のURLの下に「ルート」します。
たとえば、 DjangoWebサイト自体のURLconfの抜粋を次に示します。 これには、他の多くのURLconfが含まれています。
from django.urls import include, path
urlpatterns = [
# ... snip ...
path('community/', include('aggregator.urls')),
path('contact/', include('contact.urls')),
# ... snip ...
]
Djangoが include()を検出すると、その時点までに一致したURLの部分を切り取り、残りの文字列をインクルードされたURLconfに送信してさらに処理します。
別の可能性は、 path()インスタンスのリストを使用して追加のURLパターンを含めることです。 たとえば、次のURLconfについて考えてみます。
from django.urls import include, path
from apps.main import views as main_views
from credit import views as credit_views
extra_patterns = [
path('reports/', credit_views.report),
path('reports/<int:id>/', credit_views.report),
path('charge/', credit_views.charge),
]
urlpatterns = [
path('', main_views.homepage),
path('help/', include('apps.help.urls')),
path('credit/', include(extra_patterns)),
]
この例では、/credit/reports/
URLはcredit_views.report()
Djangoビューによって処理されます。
これは、単一のパターンプレフィックスが繰り返し使用されるURLconfから冗長性を削除するために使用できます。 たとえば、次のURLconfについて考えてみます。
from django.urls import path
from . import views
urlpatterns = [
path('<page_slug>-<page_id>/history/', views.history),
path('<page_slug>-<page_id>/edit/', views.edit),
path('<page_slug>-<page_id>/discuss/', views.discuss),
path('<page_slug>-<page_id>/permissions/', views.permissions),
]
共通パスプレフィックスを1回だけ記述し、異なるサフィックスをグループ化することで、これを改善できます。
from django.urls import include, path
from . import views
urlpatterns = [
path('<page_slug>-<page_id>/', include([
path('history/', views.history),
path('edit/', views.edit),
path('discuss/', views.discuss),
path('permissions/', views.permissions),
])),
]
キャプチャされたパラメータ
インクルードされたURLconfは、親URLconfからキャプチャされたパラメータを受け取るため、次の例が有効です。
# In settings/urls/main.py
from django.urls import include, path
urlpatterns = [
path('<username>/blog/', include('foo.urls.blog')),
]
# In foo/urls/blog.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.blog.index),
path('archive/', views.blog.archive),
]
上記の例では、キャプチャされた"username"
変数は、予想どおり、含まれているURLconfに渡されます。
関数を表示するための追加オプションの受け渡し
URLconfには、Pythonディクショナリとして、ビュー関数に追加の引数を渡すことができるフックがあります。
path()関数は、オプションの3番目の引数を取ることができます。これは、view関数に渡す追加のキーワード引数の辞書である必要があります。
例えば:
from django.urls import path
from . import views
urlpatterns = [
path('blog/<int:year>/', views.year_archive, {'foo': 'bar'}),
]
この例では、/blog/2005/
へのリクエストに対して、Djangoはviews.year_archive(request, year=2005, foo='bar')
を呼び出します。
この手法は、シンジケーションフレームワークで使用され、メタデータとオプションをビューに渡します。
紛争への対処
名前付きキーワード引数をキャプチャし、追加の引数の辞書に同じ名前の引数を渡すURLパターンを持つことができます。 これが発生すると、URLにキャプチャされた引数の代わりに、ディクショナリの引数が使用されます。
include()に追加オプションを渡す
同様に、 include()に追加のオプションを渡すことができ、インクルードされたURLconfの各行に追加のオプションが渡されます。
たとえば、これら2つのURLconfセットは機能的に同一です。
1つ設定します。
# main.py
from django.urls import include, path
urlpatterns = [
path('blog/', include('inner'), {'blog_id': 3}),
]
# inner.py
from django.urls import path
from mysite import views
urlpatterns = [
path('archive/', views.archive),
path('about/', views.about),
]
セット2:
# main.py
from django.urls import include, path
from mysite import views
urlpatterns = [
path('blog/', include('inner')),
]
# inner.py
from django.urls import path
urlpatterns = [
path('archive/', views.archive, {'blog_id': 3}),
path('about/', views.about, {'blog_id': 3}),
]
行のビューが実際にそれらのオプションを有効として受け入れるかどうかに関係なく、追加のオプションは、含まれるURLconfのすべての行に常に渡されることに注意してください。 このため、この手法は、含まれているURLconf内のすべてのビューが、渡した追加のオプションを受け入れることが確実な場合にのみ役立ちます。
URLの逆解決
Djangoプロジェクトで作業する際の一般的なニーズは、生成されたコンテンツ(ビューとアセットのURL、ユーザーに表示されるURLなど)に埋め込むため、またはサーバー上のナビゲーションフローを処理するために、最終的な形式でURLを取得できることです。サイド(リダイレクトなど)
これらのURLをハードコーディングすることは避けることが強く望まれます(面倒で、スケーラブルではなく、エラーが発生しやすい戦略)。 同様に危険なのは、URLconfによって記述された設計と並行するURLを生成するためのアドホックメカニズムを考案することです。これにより、時間の経過とともに古くなるURLが生成される可能性があります。
言い換えれば、必要なのはDRYメカニズムです。 他の利点の中でも、古いURLを検索して置き換えるためにすべてのプロジェクトのソースコードを調べなくても、URLデザインを進化させることができます。
URLを取得するために利用できる主な情報は、IDです(例: 名前)それを処理する担当のビューの。 正しいURLのルックアップに必ず参加する必要があるその他の情報は、ビュー引数のタイプ(位置、キーワード)と値です。
Djangoは、URLマッパーがURLデザインの唯一のリポジトリであるようなソリューションを提供します。 URLconfを使用してフィードすると、双方向で使用できます。
- ユーザー/ブラウザーによって要求されたURLから始めて、適切なDjangoビューを呼び出し、URLから抽出された値とともに必要な引数を提供します。
- 対応するDjangoビューの識別と、それに渡される引数の値から始めて、関連するURLを取得します。
1つ目は、前のセクションで説明した使用法です。 2つ目は、 URLの逆解決、逆URLマッチング、逆URLルックアップ、または単に URL逆として知られているものです。
Djangoは、URLが必要なさまざまなレイヤーに一致するURL反転を実行するためのツールを提供します。
- テンプレートの場合::ttag: `url` テンプレートタグを使用します。
- Pythonコードの場合: reverse()関数を使用します。
- DjangoモデルインスタンスのURLの処理に関連する高レベルのコード: get_absolute_url()メソッド。
例
このURLconfエントリをもう一度考えてみましょう。
from django.urls import path
from . import views
urlpatterns = [
#...
path('articles/<int:year>/', views.year_archive, name='news-year-archive'),
#...
]
この設計によれば、 nnnn 年に対応するアーカイブのURLは/articles/<nnnn>/
です。
これらは、次を使用してテンプレートコードで取得できます。
<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a>
{# Or with the year in a template context variable: #}
<ul>
{% for yearvar in year_list %}
<li><a href="{% url 'news-year-archive' yearvar %}">{{ yearvar }} Archive</a></li>
{% endfor %}
</ul>
またはPythonコードの場合:
from django.http import HttpResponseRedirect
from django.urls import reverse
def redirect_to_year(request):
# ...
year = 2006
# ...
return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))
何らかの理由で、年次記事アーカイブのコンテンツが公開されているURLを変更する必要があると判断された場合は、URLconfのエントリを変更するだけで済みます。
ビューが一般的な性質のものである一部のシナリオでは、URLとビューの間に多対1の関係が存在する場合があります。 このような場合、URLを逆にするときに、ビュー名は十分な識別子ではありません。 次のセクションを読んで、Djangoがこれに提供するソリューションについて知ってください。
URLパターンの命名
URL反転を実行するには、上記の例で行ったように、名前付きURLパターンを使用する必要があります。 URL名に使用される文字列には、任意の文字を含めることができます。 有効なPython名に制限されていません。
URLパターンに名前を付けるときは、他のアプリケーションの名前の選択と衝突する可能性が低い名前を選択してください。 URLパターンをcomment
と呼び、別のアプリケーションが同じことを行う場合、 reverse()が見つけるURLは、プロジェクトのurlpatterns
リストの最後にあるパターンによって異なります。
おそらくアプリケーション名から派生した(comment
ではなくmyapp-comment
など)URL名にプレフィックスを付けると、衝突の可能性が低くなります。
ビューを上書きする場合は、別のアプリケーションとして同じURL名を意図的に選択できます。 たとえば、一般的な使用例は、 LoginView をオーバーライドすることです。 Djangoの一部とほとんどのサードパーティアプリは、このビューにlogin
という名前のURLパターンがあることを前提としています。 カスタムログインビューがあり、そのURLにlogin
という名前を付けると、 [の後のurlpatterns
にある限り、 reverse()はカスタムビューを検索します。 X154X]が含まれています(含まれている場合)。
引数が異なる場合は、複数のURLパターンに同じ名前を使用することもできます。 reverse()は、URL名に加えて、引数の数とキーワード引数の名前に一致します。 パスコンバーターは、ValueError
を上げて、一致しないことを示すこともできます。詳細については、カスタムパスコンバーターの登録を参照してください。
URL名前空間
序章
URL名前空間を使用すると、異なるアプリケーションが同じURL名を使用している場合でも、名前付きURLパターンを一意に逆にすることができます。 サードパーティのアプリでは、(チュートリアルで行ったように)常に名前空間付きのURLを使用することをお勧めします。 同様に、アプリケーションの複数のインスタンスがデプロイされている場合は、URLを逆にすることもできます。 つまり、1つのアプリケーションの複数のインスタンスが名前付きURLを共有するため、名前空間はこれらの名前付きURLを区別する方法を提供します。
URL名前空間を適切に使用するDjangoアプリケーションは、特定のサイトに複数回デプロイできます。 たとえば、 django.contrib.admin には AdminSite クラスがあり、admin の複数のインスタンスをデプロイできます。 後の例では、チュートリアルの投票アプリケーションを2つの異なる場所にデプロイして、2つの異なる対象者(作成者と発行者)に同じ機能を提供できるようにするアイデアについて説明します。
URL名前空間は2つの部分に分かれており、どちらも文字列です。
- アプリケーションの名前空間
- これは、デプロイされているアプリケーションの名前を表します。 単一のアプリケーションのすべてのインスタンスは、同じアプリケーション名前空間を持ちます。 たとえば、Djangoの管理アプリケーションには、
'admin'
というある程度予測可能なアプリケーション名前空間があります。 - インスタンスの名前空間
- これは、アプリケーションの特定のインスタンスを識別します。 インスタンスの名前空間は、プロジェクト全体で一意である必要があります。 ただし、インスタンスの名前空間はアプリケーションの名前空間と同じにすることができます。 これは、アプリケーションのデフォルトインスタンスを指定するために使用されます。 たとえば、デフォルトのDjango管理インスタンスのインスタンス名前空間は
'admin'
です。
名前空間URLは、':'
演算子を使用して指定されます。 たとえば、管理アプリケーションのメインインデックスページは、'admin:index'
を使用して参照されます。 これは、'admin'
の名前空間、および'index'
の名前付きURLを示します。
名前空間はネストすることもできます。 名前付きURL 'sports:polls:index'
は、トップレベルの名前空間'sports'
内でそれ自体が定義されている名前空間'polls'
で'index'
という名前のパターンを検索します。
名前空間のURLを逆にする
名前空間付きのURLが与えられた場合(例: 'polls:index'
)を解決するために、Djangoは完全修飾名をパーツに分割してから、次のルックアップを試行します。
まず、Djangoは一致するアプリケーション名前空間(この例では
'polls'
)を探します。 これにより、そのアプリケーションのインスタンスのリストが生成されます。現在定義されているアプリケーションがある場合、DjangoはそのインスタンスのURLリゾルバーを見つけて返します。 現在のアプリケーションは、 reverse()関数の
current_app
引数で指定できます。:ttag: `url` テンプレートタグは、現在解決されているビューの名前空間を RequestContext の現在のアプリケーションとして使用します。 request.current_app 属性に現在のアプリケーションを設定することで、このデフォルトをオーバーライドできます。
現在のアプリケーションがない場合、Djangoはデフォルトのアプリケーションインスタンスを探します。 デフォルトのアプリケーションインスタンスは、インスタンス名前空間がアプリケーション名前空間と一致するインスタンスです(この例では、
'polls'
と呼ばれるpolls
のインスタンス)。 。デフォルトのアプリケーションインスタンスがない場合、Djangoは、インスタンス名が何であれ、アプリケーションの最後にデプロイされたインスタンスを選択します。
指定された名前空間が手順1のアプリケーション名前空間と一致しない場合、Djangoは名前空間をインスタンス名前空間として直接検索しようとします。
ネストされた名前空間がある場合、ビュー名のみが解決されなくなるまで、名前空間の各部分に対してこれらの手順が繰り返されます。 ビュー名は、見つかった名前空間のURLに解決されます。
例
この解決戦略の実際を示すために、チュートリアルのpolls
アプリケーションの2つのインスタンスの例を考えてみましょう。1つは'author-polls'
と呼ばれ、もう1つは'publisher-polls'
と呼ばれます。 ポーリングを作成および表示するときにインスタンスの名前空間が考慮されるように、そのアプリケーションを拡張したと仮定します。
from django.urls import include, path
urlpatterns = [
path('author-polls/', include('polls.urls', namespace='author-polls')),
path('publisher-polls/', include('polls.urls', namespace='publisher-polls')),
]
from django.urls import path
from . import views
app_name = 'polls'
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
path('<int:pk>/', views.DetailView.as_view(), name='detail'),
...
]
この設定を使用すると、次のルックアップが可能です。
インスタンスの1つが最新の場合、たとえば、インスタンス
'author-polls'
で詳細ページをレンダリングしていた場合、'polls:index'
は'author-polls'
インスタンスのインデックスページに解決されます。 NS 次の両方の結果は"/author-polls/"
になります。クラスベースのビューのメソッドでは、次のようになります。
reverse('polls:index', current_app=self.request.resolver_match.namespace)
およびテンプレート内:
{% url 'polls:index' %}
現在のインスタンスがない場合(たとえば、サイトの別の場所にページをレンダリングしていた場合)、
'polls:index'
はpolls
の最後に登録されたインスタンスに解決されます。 デフォルトのインスタンス('polls'
のインスタンス名前空間)がないため、登録されているpolls
の最後のインスタンスが使用されます。urlpatterns
で最後に宣言されているため、これは'publisher-polls'
になります。'author-polls:index'
は、常にインスタンス'author-polls'
のインデックスページに解決されます('publisher-polls'
の場合も同様)。
デフォルトのインスタンス(つまり、'polls'
という名前のインスタンス)もあった場合、上記からの唯一の変更は、現在のインスタンス(上記のリストの2番目の項目)がない場合です。 この場合、'polls:index'
は、urlpatterns
で最後に宣言されたインスタンスではなく、デフォルトインスタンスのインデックスページに解決されます。
URL名前空間と含まれるURLconf
インクルードされたURLconfのアプリケーション名前空間は、2つの方法で指定できます。
まず、含まれているURLconfモジュールのapp_name
属性を、urlpatterns
属性と同じレベルで設定できます。 urlpatterns
自体のリストではなく、実際のモジュールまたはモジュールへの文字列参照を include()に渡す必要があります。
from django.urls import path
from . import views
app_name = 'polls'
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
path('<int:pk>/', views.DetailView.as_view(), name='detail'),
...
]
from django.urls import include, path
urlpatterns = [
path('polls/', include('polls.urls')),
]
polls.urls
で定義されたURLには、アプリケーション名前空間polls
があります。
次に、埋め込まれた名前空間データを含むオブジェクトを含めることができます。 include()
path()または re_path()インスタンスのリストを作成すると、そのオブジェクトに含まれるURLがグローバル名前空間に追加されます。 ただし、次を含む2タプルをinclude()
することもできます。
(<list of path()/re_path() instances>, <application namespace>)
例えば:
from django.urls import include, path
from . import views
polls_patterns = ([
path('', views.IndexView.as_view(), name='index'),
path('<int:pk>/', views.DetailView.as_view(), name='detail'),
], 'polls')
urlpatterns = [
path('polls/', include(polls_patterns)),
]
これには、指定されたアプリケーション名前空間に指定されたURLパターンが含まれます。
インスタンスの名前空間は、 include()のnamespace
引数を使用して指定できます。 インスタンスの名前空間が指定されていない場合、デフォルトで、含まれているURLconfのアプリケーションの名前空間になります。 これは、その名前空間のデフォルトインスタンスにもなることを意味します。