路由命名

path(route, view, kwargs=None, name=None)

前面几章我们介绍了path函数的route(路径匹配)、view(视图函数,在后面还会详细介绍)、kwargs(参数绑定)。接下来让我们看看name。

路由命名

name(路由命名):对你的URL进行命名,可以让你能够在Django的任意处,尤其是模板内显式地引用它。相当于给URL取了个全局变量名,你只需要修改这个全局变量的值,在整个Django中引用它的地方也将同样获得改变。这是极为古老、朴素和有用的设计思想,而且这种思想无处不在。

使用路由命名定义路由

还是用之前的例子来说明一下:

    path('articles/2003/', views.special_case_2003, name='special_case_2003'),
    re_path(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive, name='archive1'),
    path('articles/<int:year>/<int:month>/', views.month_archive, name='archive2')

示例在原先的基础上增加了name属性,即使用了路由命名来指明了路由的名称。

根据命名获取路由

既然是对路由进行命名,那么肯定需要通过名称获取到路由的详细路径

reverse反解析

使用reverse函数,可以根据路由名称,返回具体的路径。继续拿上面的例子进行说明:

from django.urls import reverse

def func(request):
    path1 = reverse('special_case_2003') # 返回/articles/2003/ #无参数path反解析
    path2 = reverse('archive1', args=(2007, 12)) #返回/article/2007/12 #未命名分组参数反解析
    path3 = reverse('archive2', kwargs={'year': 2007, 'month': 12}) #返回/article/2007/12 #命名分组参数反解析

注意:

  • 当命名的路由有参数时,reverse函数里面也要传入参数。
  • 当路由使用未命名分组参数时,reverse函数使用args元组传入参数。
  • 当路由使用命名分组参数时,reverse函数使用kwargs字典传入参数。
  • 关于路路由的参数说明,可详见上一章Django路由系统-参数传递

模板标签获取路由

关于模板语言会在后续详细说明,本章节主要说明其怎么通过命名获取url

  • 获取无参数URL

通过上面的介绍我们可以很明显地看出路由命名的作用。当我们需要使用Django URLConf中配置的url地址时,我们不需要记住冗长的地址。相反我们使用命名来代替它。而且,就算配置的地址发生了改变,因为我们使用的是路由的别名,所以我们也不用全局搜索去更改全部的地址引用。这在一个大型的项目中是十分有用的。

命名空间

思考这样一个问题,当我们的项目中包含很多的应用后,每个应用又有许多的路由,难免会出现在不同的应用中定义了相同的路由别名。这时,我们再用reverse或者在模板中获取路由路径,往往就会得不到我们想要的结果。这个时候,我们需要再为路由别名定义一层命名空间。

应用命名空间

它表示正在部署的应用的名称。一个应用的每个实例具有相同的应用命名空间。例如,可以预见Django 的管理站点的应用命名空间是'admin'。

应用命名空间的实现方式:

  • 在本应用的URLconf中实现

      #myapp/urls.py
      from django.urls import path
      from myapp import views
    
      app_name = "myapp"
      urlpatterns = [
          path('hello/', views.hello_view, {'names': 'test'}, name='hello'),
      ]
    
  • 使用以下内容的2元组实现:

    (<list of path()/re_path() instances>, <application namespace>)

    例如:

      from django.urls import include, path
    
      from . import views
    
      polls_patterns = ([
          path('', views.IndexView.as_view(), name='index'),
          path('<int:pk>/', views.DetailView.as_view(), name='detail'),
      ], 'polls')
    
      urlpatterns = [
          path('polls/', include(polls_patterns)),
      ]
    
  • 在早期的版本中还支持在父路由中实现,2.0新版本后已经不支持了

      urlpatterns = [
          url(r'^help/', include('apps.help.urls', namespace='help', app_name='help')),
          url(r'^ineedhelp/', include('apps.help.urls', namespace='otherhelp', app_name='help')),
      ]
    

很显然,第一种方式更加地简洁易懂。

实例命名空间

它表示应用的一个特定的实例。实例的命名空间在你的全部项目中应该是唯一的。但是,一个实例的命名空间可以和应用的命名空间相同。它用于表示一个应用的默认实例。例如,Django 管理站点实例具有一个默认的实例命名空间'admin'。 URL的命名空间使用':' 操作符指定。例如,管理站点应用的主页使用' admin:index '。它表示' admin ' 的一个命名空间和' index ' 的一个命名URL.

实例命名空间的实现方式:

  • 路由分发时实现

      from django.urls import include, path
    
      urlpatterns = [
          path('author-polls/', include('polls.urls',                             namespace='author-polls')),
          path('publisher-polls/', include('polls.urls',                          namespace='publisher-polls')),
      ]
    
  • 对应应用命名空间二元组实现

      from django.urls import include, path
    
      from . import views
    
      polls_patterns = ([
          path('', views.IndexView.as_view(), name='index'),
          path('<int:pk>/', views.DetailView.as_view(), name='detail'),
      ], 'polls')
    
      urlpatterns = [
          path('polls/', include(polls_patterns, namespace='polls')),
      ]
    

解析路由命名空间URL

命名空间URL解析与路由命名解析基本相同,只是在原先的命名前加上其对应的命名空间即可。例如polls:index。让我们看看Django是如何解析应用命名空间和实例命名空间。

#urls.py
from django.contrib import admin
from django.urls import path, include
from myapp import urls as myapp_urls

urlpatterns = [
    path('admin/', admin.site.urls),
    path('myapp/', include(myapp_urls, namespace='myins'))
]

#myapp.urls
from django.urls import path
from myapp import views

app_name = "myapp"
urlpatterns = [
    path('hello/', views.hello_view, {'names': 'test'}, name='hello'),
]
  • 使用应用命名空间:

    ➜  myproject python3 manage.py shell
    Python 3.6.4 (v3.6.4:d48ecebad5, Dec 18 2017, 21:07:28)
    [GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    (InteractiveConsole)
    >>> from django.urls import reverse
    >>> reverse('myapp:hello')
    '/myapp/hello/'
    >>>
    
  • 使用实例命名空间:

    ➜  myproject python3 manage.py shell
    Python 3.6.4 (v3.6.4:d48ecebad5, Dec 18 2017, 21:07:28)
    [GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    (InteractiveConsole)
    >>> from django.urls import reverse
    >>> reverse('myins:hello')
    '/myapp/hello/'
    >>>
    
  • 同时使用:

    ➜  myproject python3 manage.py shell
    Python 3.6.4 (v3.6.4:d48ecebad5, Dec 18 2017, 21:07:28)
    [GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    (InteractiveConsole)
    >>> from django.urls import reverse
    >>> reverse('myins:hello', current_app='myapp')
    '/myapp/hello/'
    >>>
    

命名空间解析流程

When given a namespaced URL (e.g. 'polls:index') to resolve, Django splits the fully qualified name into parts and then tries the following lookup:

  1. First, Django looks for a matching application namespace (in this example, 'polls'). This will yield a list of instances of that application.

  2. If there is a current application defined, Django finds and returns the URL resolver for that instance. The current application can be specified with the current_app argument to the reverse() function.

    The url template tag uses the namespace of the currently resolved view as the current application in a RequestContext. You can override this default by setting the current application on the request.current_app attribute.

  3. If there is no current application. Django looks for a default application instance. The default application instance is the instance that has an instance namespace matching the application namespace (in this example, an instance of polls called 'polls').

  4. If there is no default application instance, Django will pick the last deployed instance of the application, whatever its instance name may be.

  5. If the provided namespace doesn’t match an application namespace in step 1, Django will attempt a direct lookup of the namespace as an instance namespace.

If there are nested namespaces, these steps are repeated for each part of the namespace until only the view name is unresolved. The view name will then be resolved into a URL in the namespace that has been found.

Copyright © itrunner.cn 2020 all right reserved,powered by Gitbook该文章修订时间: 2022-08-28 07:44:16

results matching ""

    No results matching ""