ルーティング - Django

1.ディレクトリ構成

  • pythonApp
    • env
      • learn_routing
        • first
          • migrations
            • ...
            • templates
              • first
                • index.html
          • __init__.py
          • admin.py
          • apps.py
          • models.py
          • tests.py
          • views.py
        • learn_routing
          • ...
        • next
          • migrations
            • ...
            • templates
              • next
                • index.html
          • __init__.py
          • admin.py
          • apps.py
          • models.py
          • tests.py
          • views.py
        • db.sqlite3
        • manage.py
      • ...

2.ファイルの内容

templates

pythonApp\routing\learn_routing\first\templates\first\index.html

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <h1>first/index</h1>
  <p><a href="{% url 'index' %}">index</a></p>
</body>
</html>

pythonApp\routing\learn_routing\next\templates\next\index.html

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <h1>next/index</h1>
  <p><a href="{% url 'index' %}">index</a></p>
</body>
</html>
views.py

pythonApp\routing\learn_routing\first\views.py

from django.shortcuts import render
from django.http import HttpResponse

# Create your views here.
def index(request):
  return render(request, 'first/index.html')

pythonApp\routing\learn_routing\next\views.py

from django.shortcuts import render
from django.http import HttpResponse

# Create your views here.
def index(request):
  return render(request, 'next/index.html')
urls.py

pythonApp\routing\learn_routing\learn_routing\urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('first/', include('first.urls')),
    path('next/', include('next.urls')),
]

pythonApp\routing\learn_routing\first\urls.py

from django.urls import path
from . import views

urlpatterns = [
  path('', views.index, name='index')
]

pythonApp\routing\learn_routing\next\urls.py

from django.urls import path
from . import views

urlpatterns = [
  path('', views.index, name='index')
]
settings.py

pythonApp\routing\learn_routing\learn_routing\settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'first',
    'next'
]

3.名前空間

「 2.ファイルの内容 」のリンクの書き方を「 <a href="{% url 'index' %}">index</a> 」としています。

「 first/index.html 」も「 next/index.html 」も「 <a href="{% url 'index' %}">index</a> 」としていますが、どちらもページの遷移先は、「 next/index.html 」に遷移します。

「 first/index.html 」も「 next/index.html 」それぞれページの遷移ができるように、名前空間を設定します。

名前空間を指定するために、「 pythonApp\routing\learn_routing\learn_routing\urls.py 」を以下のように変更します。

pythonApp\routing\learn_routing\learn_routing\urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('first/', include(( ('first.urls', 'first') ))),
    path('next/', include( ('next.urls', 'next') )),
]

index.html をそれぞれ次のように変更します。

pythonApp\routing\learn_routing\first\templates\first\index.html

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <h1>first/index</h1>
  <p><a href="{% url 'next:index' %}">index</a></p>
</body>
</html>

pythonApp\routing\learn_routing\next\templates\next\index.html

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <h1>next/index</h1>
  <p><a href="{% url 'first:index' %}">index</a></p>
</body>
</html>

以下のように include の引数に namespace を指定するやり方は、Django1.9 から使えなくなったようです。

urlpatterns = [
    url('first/', include('first.urls', namespace="first")),
    ...
]

The app_name argument to include() has been replaced by passing a 2-tuple (as above), or passing an object or module with an app_name attribute (as below). If the app_name is set in this new way, the namespace argument is no longer required. It will default to the value of app_name.

include() の app_name 引数は、2 タプルを渡す (上記のように) か、app_name 属性を持つオブジェクトまたはモジュールを渡す (下記のように) ように置き換えられました。app_name がこの新しい方法で設定されている場合、namespace 引数は不要になります。デフォルトで app_name の値になります。

4.アプリ側の urls.py で指定する名前空間

アプリ側の「 urls.py 」でも名前空間を設定できます。

pythonApp\routing\learn_routing\learn_routing\urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('first/', include('first.urls')),
    path('next/', include('next.urls')),
]

pythonApp\routing\learn_routing\first\urls.py

from django.urls import path
from . import views

app_name = 'first'
urlpatterns = [
  path('', views.index, name='index')
]

pythonApp\routing\learn_routing\next\urls.py

from django.urls import path
from . import views

app_name = 'next'
urlpatterns = [
  path('', views.index, name='index')
]

templates は、「 3.名前空間 」の内容と同じです。