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.