1、爲何須要url命名?
由於url是常常變化的。若是在代碼中寫死可能會常常改代碼。給url取個名字,之後使用url的時候就使用他的名字進行反轉就能夠了,就不須要寫死url了。python
需求:訪問app主頁,若是沒登陸則自動跳轉至登陸頁面,已經登陸則留在app主頁。shell
項目下建立兩個app:django
django-admin startapp app01 django-admin startapp app02
項目的settings.py
中添加這兩個應用:服務器
INSTALLED_APPS = [ ... 'apps.app01', 'apps.app02' ]
項目的urls.py
中添加URL映射:app
from django.urls import path, include urlpatterns = [ ... path('app01/', include('apps.app01.urls')), path('app02/', include('apps.app02.urls')), ]
app01和app02分別新建urls.py
並配置:函數
from django.urls import path from . import views urlpatterns = [ path('', views.index), path('signin/', views.login), ]
app01和app02的views.py
中:url
# 如下是app01/views.py from django.http import HttpResponse from django.shortcuts import redirect def index(request): username = request.GET.get('username') if username: return HttpResponse('app01首頁') else: return redirect('./login/') def login(request): return HttpResponse('app01登陸頁面') # 如下是app02/views.py from django.http import HttpResponse from django.shortcuts import redirect def index(request): username = request.GET.get('username') if username: return HttpResponse('app02首頁') else: return redirect('./login/') def login(request): return HttpResponse('app02登陸頁面')
啓動服務:spa
python manage.py runserver
訪問 http://127.0.0.1:8000/app01?username='onefine'
code
訪問 http://127.0.0.1:8000/app02?username='onefine'
server
訪問 http://127.0.0.1:8000/app01/
訪問 http://127.0.0.1:8000/app02/
一切正常!
如今有了新的需求:登陸時的url由login變爲signin。在目前的項目中,更改須要涉及四個文件…額…
如今採用url命名來防止這種需求。
2、如何給一個url指定名稱?
在path
函數中,傳遞一個name
參數就能夠指定。
path('', views.index, name='index')
app01和app02下的urls.py
配置:
urlpatterns = [ path('', views.index, name="index"), path('signin/', views.login, name="login"), ]
app01和app02的views.py
中:
# 如下是app01/views.py from django.http import HttpResponse from django.shortcuts import redirect, reverse def index(request): username = request.GET.get('username') if username: return HttpResponse('app01首頁') else: # url反轉,url重定向 return redirect(reverse('login')) def login(request): return HttpResponse('app01登陸頁面') # 如下是app02/views.py from django.http import HttpResponse from django.shortcuts import redirect, reverse def index(request): username = request.GET.get('username') if username: return HttpResponse('app02首頁') else: return redirect(reverse('login')) def login(request): return HttpResponse('app02登陸頁面')
從新啓動服務器,輸入 http://127.0.0.1:8000/app02
輸入 http://127.0.0.1:8000/app01
你沒看錯,它確實跳轉的是app2下面的signin,這是怎麼回事呢?
3、應用(app)命名空間:
在多個app之間,有可能產生同名的url。這時候爲了不反轉url的時候產生混淆,能夠使用應用命名空間,來作區分。定義應用命名空間很是簡單,只要在app
的urls.py
中定義一個叫作app_name
的變量,來指定這個應用的命名空間便可。
app01下的urls.py
配置,app02相似:
from django.urls import path from . import views # 應用命名空間 app_name = 'app01' urlpatterns = [ path('', views.index, name="index"), path('signin/', views.login, name="login"), ]
之後在作反轉的時候就能夠使用應用命名空間:url名稱
的方式進行反轉。
app01的views.py
中,app02相似:
from django.http import HttpResponse from django.shortcuts import redirect, reverse def index(request): username = request.GET.get('username') if username: return HttpResponse('app01首頁') else: return redirect(reverse('app01:login')) def login(request): return HttpResponse('app01登陸頁面')
好了,完美貼合需求。
4、實例命名空間:
一個app能夠建立多個實例。能夠使用多個url映射到同一個app。這就會產生一個問題:之後在作反轉的時候,若是使用應用命名空間,那麼就會發生混淆。
項目下urls.py
文件:
urlpatterns = [ path('app01/', include('apps.app01.urls')), path('app02/', include('apps.app02.urls')), # 新添加的 path('app03/', include('apps.app01.urls')), ]
重啓服務訪問 http://127.0.0.1:8000/app03
還真是脆弱。。。
爲了不這個問題。咱們能夠使用實例命名空間。實例命名空間只要在include
函數中傳遞一個namespace
變量便可。
項目下urls.py
文件:
urlpatterns = [ url(r'^admin/', admin.site.urls), # re_path(r'^$', views.index), path('app01/', include('apps.app01.urls', namespace='app01')), path('app02/', include('apps.app02.urls', namespace='app02')), # 同一個app下的第二個實例,實例命名空間 path('app03/', include('apps.app01.urls'), namespace='app03'), ]
之後在作反轉的時候,就能夠根據實例命名空間來指定具體的url。
app01下的views.py
,app02相似:
from django.http import HttpResponse from django.shortcuts import redirect, reverse def index(request): username = request.GET.get('username') if username: return HttpResponse('app01首頁') else: # 獲取當前實例的命名空間 current_namespace = request.resolver_match.namespace return redirect(reverse('%s:login' % current_namespace)) def login(request): return HttpResponse('app01登陸頁面')
輸入http://127.0.0.1:8000/app03/
輸入 http://127.0.0.1:8000/app03?username='onefine'
欣慰!
注意:在使用實例命名空間以前,必須先指定一個應用命名空間——在子url.py中添加app_name變量。
'Specifying a namespace in include() without providing an app_name ’ django.core.exceptions.ImproperlyConfigured: Specifying a namespace in include() without providing an app_name is not supported. Set the app_name attribute in the included module, or pass a 2-tuple containing the list of patterns and app_name instead.