django框架学习:三十.反向解析url和命名空间

前言

反向解析url

在实际的django项目中,经常需要获取某条url,未生成的内容配置url连接。

例如:我在页面上展示一系列文章列表,每个条目都是超级链接,点击就进入该文章的详细页面,路由配置:path('post/<int:pk>/',views.some_view),

在前端中需要为HTML标签<a>标签herf属性提供一个诸如http://www.xxx.com/post/3/的值。其中的域名部门django会自动帮你添加,我们需要关注的是怎么添加/post/3/。

此时一定不能硬编码url为/post/3/,那样费事,不可伸缩,容易出错。试想如果哪天因为某些原因,需要将urlconf中的表达式改成entry/<int:pk>/,为了让链接正常工作,必需修改对应的herf属性值,于是你去项目里将所有的post/3/改为entry/3/吗?显然不合理。

我们需要一种安全可靠,自适应的机制,当修改urlconf中的代码后,无需在项目源码中大范围的搜索,替换失效的硬编码url,为了解决这个问题,django中提供了一种解决方案,只需在url中提供一个name参数,并赋值你自定义的好记的,直观的字符串。通过这个name参数,可以反向解析url,反向url匹配,反向查询或者简单的url反查。

在需要解析url的地方,对于不同层级,django提供了不同工具的用于url反查:

>在模版语言中:使用url模板标签

>在pyhon代码中:使用reverse()函数(0写视图函数等情况时)

>在更高层的预处理django模型实例相关的代码中:使用 get_basolute_url()方法。(也就是在模型model中)

实例:

from django.urls import path

from .import views

 

2020年对应的归档url是/articles/2019/。

对应的在模板代码中使用下面的模版方法获得他们:

 

 在python代码中,这样使用:

 

 其中起到核心作用的是我们通过name=“news-year-archive”为那条url起了一个可以被引用的名称。

url名称name使用的字符串可以包含任何你喜欢的字符,但是过度放纵有可能重名带来的冲突,比如两个app取了相同的name,为了解决这个问题,又引出了下面的命名空间。

url命名空间

url命名空间可以保证反查到唯一的url,第三方应用始终使用命名空间是一个很好地做法,类似的他还允许你在一个应用有多个实例部署的情况下反查url,换句话讲,因为一个应用的多个实例共享相同的命名url,命名空间提供了一种区分这些命名url的方法。

实现命名空间的做法很简单,在urlconf文件中添加app_name="polls"和namespace="author_polls"类似的定义。

实例:

以上面polls的应用的两个实例为例:"publisher-polls"和"author-polls"。

假设我们已经在创建和显示投票时考虑了实例命名空间的问题,代码如下:

urls.py

 

 app应用urls.py

 

 如果您当前的app实例是其中的一个,例如:我们正在渲染实例“author-polls”中的detail 视图,“polls:index”将解析到“author-polls”实例的index视图。

根据以上设置可以使用一下查询:

在基于类的方法中:

reverse('polls':index,current_app=self.request.resolver_match.namespace)

在模板中:

{% url polls:index" %}

如果没有当前的app实例,例如如果我们在站点其他地方渲染一个页面,"polls:index"将解析到polls注册的最后一个app实例空间,因为没有默认的实例,将使用注册polls的嘴周一个声明。

url命名空间和include的urlconf

可以通过两种方式指定ibclude和urlconf的应用名称空间

第一种

在include的urlconf模块中设置与urlpatterns属性相同级别的app_name属性。必须将实际模块或模块的字符串引用传递到include(),而不是urlpatterns本身的列表。

polls/urls.py:

from django.urls import path

from . import views

app_name = 'polls'

urlpatterns = [

path('', views.IndexView.as_view(), name='index'),

path('<int:pk>/', views.DetailView.as_view(), name='detail'),

]

urls.py:

from django.urls import include, path

urlpatterns = [

path('polls/', include('polls.urls')),

]

此时,polls.urls中定义的URL将具有应用名称空间polls。

第二种

include一个包含嵌套命名空间数据的对象,格式如下:

(<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)),

]

 

这将include指定的URL模式到给定的app命名空间。

可以使用include()的namespace参数指定app实例命名空间。如果未指定,则app实例命名空间默认为URLconf的app命名空间。

posted @ 2020-05-11 16:44  流水小哥  阅读(308)  评论(0编辑  收藏  举报