Djangoではurls.pyなどで、名前付きのURL(url関数を使ってnameを指定)することで、URLを名前から逆引きすることができますが、この名前が衝突するとどうなるでしょう。
答え:一番最後に定義されたものが使われます。
以下、その例。
プロジェクトの構造
myproject │ manage.py │ myproject.db │ settings.py │ urls.py │ __init__.py │ ├─myapp1 │ models.py │ urls.py │ views.py │ __init__.py │ ├─myapp2 │ models.py │ urls.py │ views.py │ __init__.py │ └─templates ├─myapp1 │ index.html │ └─myapp2 index.html
myapp1とmyapp2を作りました。
urls.py では myapp1.urls と myapp2.urls に委譲しています。
from django.conf.urls.defaults import * urlpatterns = patterns('', (r'', include('myapp1.urls'), (r'', include('myapp2.urls')), )
myapp1/urls.pyでは "index" という名前のURLを定義しています。
from django.conf.urls.defaults import * urlpatterns = patterns('', url(r'^myapp1/$', 'myapp1.views.index', name='index'), )
myapp2/urls.pyでも同様に "index" という名前のURLを定義しています。
from django.conf.urls.defaults import * urlpatterns = patterns('', url(r'^myapp2/$', 'myapp2.views.index', name='index'), )
myapp1/views.pyでは myapp1/index.html のテンプレートを使うビューを書いています。
from django.views.generic.simple import direct_to_template def index(request): return direct_to_template(request, 'myapp1/index.html')
myapp2/views.pyでは myapp2/index.html のテンプレートを使うビューを書いています。
from django.views.generic.simple import direct_to_template def index(request): return direct_to_template(request, 'myapp2/index.html')
テンプレートでは、それぞれのテンプレートの識別用の名前と、urlタグを使ってURLを逆引きした結果を表示するようにしています。
<h1>myapp1 template</h1> {% url index %}
さてこの状態でrunserverを実行して /myapp1/ にアクセスすると、myapp1のテンプレートでの "index" という名前で逆引きした結果が /myapp2/ になってしまいました。
/myapp2/ にアクセスした場合も /myapp2/ になっています。
このままでは、myapp1のURLの逆引きが使えません。こういった時にnamespaceを使います。
namespaceを使う
urls.pyでinclude関数の引数にnamespaceを指定します。
from django.conf.urls.defaults import * urlpatterns = patterns('', (r'', include('myapp1.urls')), # (r'', include('myapp2.urls')), (r'', include('myapp2.urls', namespace='myapp2')), )
myapp2の方にnamespaceを指定しました。
この状態だと、 "index" で逆引きした場合は、 /myapp1/ になります。
myapp2の逆引き部分を修正します。
<h1>myapp2 template</h1> {% url myapp2:index %}
名前の前にnamespaceを指定します。これで /myapp2/ でも正しい逆引きができるようになりました。
注意点
うまく解決できたように見えますが実はそんなことはないです。結局のところmyapp2の名前指定は全部修正しないといけないです。
ドキュメントには書かれていますが、applicaiton namespaceを指定しておいて、コンテキストのcurrent_appを操作するなどして表示を切り替えるほうがよく使いそうです。
また、viewsをクラスで書いた場合、include関数ではnamespaceを指定できないので、urlsプロパティの戻り値を操作する必要があったりします。