Django應用命名空間與實例命名空間

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的時候產生混淆,能夠使用應用命名空間,來作區分。定義應用命名空間很是簡單,只要在appurls.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.

相關文章
相關標籤/搜索