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.

相关文章
相关标签/搜索