全国咨询/投诉热线:400-618-4000

Django之URL反向解析介绍[传智播客]

更新时间:2019年10月15日17时07分 来源:传智播客 浏览次数:

一、urls硬编码

在反向解析和命名空间之前我们先来说说URLS硬编码,用django开发应⽤的时候,可以完全是在urls.py中硬编码配置地址,在views.py中HttpResponseRedirect()也是硬编码转向地址,当然在template中也是一样了,这样带来一个问题,如果在urls.py中修改了某个页面的地址(也就是说更改路由系统中对应的路由分发),那么所有的地方(views.py和template中)都要修改。问题出在硬编码,紧耦合使得在大量的模板中修改URLS成为富有挑战性的项目。来看下面的模板文件index.html中,我们到的链接硬编码成这样:

<li><a href="/goods/index/">url硬编码</a></li>

如果使用软编码之后,无论怎么更改路由系统中的路由分发,只有对应的namespace与name属性值不变,就不必修改在views.py和template中的url,也就是说

<li><a href="{% url "good:index" %}">url软编码</a></li>

在templates中更改为软编码之后,其实在templates,index.html文件生成的时候,仍然是

<li><a href="/goods/index/">url软编码</a></li>
Django之URL反向解析

二、URL的反向解析

在使用Django项目时,一个常见的需求是获得URL的最终形式,以用于嵌入到生成的内容中(视图中和显示给用户的URL等)或者用于处理服务器端的导航(重定向等)。 人们强烈希望不要硬编码这些URL(费力、不可扩展且容易产生错误)或者设计一种与URLconf毫不相关的专门的URL生成机制,因为这样容易导致一定程度上产生过期的URL。【推荐了解:python+人工智能课程

获取一个URL最开始想到的信息是处理它视图的标识(例如名字),查找正确的URL的其它必要的信息有视图参数的类型(位置参数、关键字参数)和值。Django提供一个办法是让URL映射是URL设计唯一的地方。你填充你的URLconf,然后可以双向使用它:

(1)根据用户/浏览器器发起的URL 请求,它调⽤用正确的Django 视图,并从URL 中提取它的参数需要的值。

(2)根据Django视图的标识和将要传递给它的参数的值,获取与之关联的URL。

第一种方式是我们常说的根据地址定位URL。

第二种方式叫做反向解析URL、反向URL 匹配、反向URL查询或者简单的URL反查。在需要URL的地方。

对于不同层级,Django提供不同的工具用于URL 反查:

(1)在模板中:使⽤用url模板标签。

(2)在Python代码中:使⽤django.core.urlresolvers.reverse() 函数。

(3)在更高层的与处理Django模型实例相关的代码中:使用get_absolute_url()方法。


1、命名空间:

URL命名空间允许你反查到唯一的命名URL模式,即使不同的应用使用相同的URL 名称。第三方应用始终使用带命名空间的URL 是一个很好的实践。类似地,它还允许你在一个应用有多个实例部署的情况下反查URL。换句话讲,因为一个应用的多个实例共享相同的命名URL,命名空间将提供一种区分这些命名URL 的方法。一个URL命名空间有两个部分,它们都是字符串:

<1>应用命名空间:

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

<2>实例命名空间:

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

# include函数的API
include(arg, namespace=None, app_name=None)
# namespace设置实例例命名空间,app_name设置应⽤用命名空间
# 不不能只设置app_name,否则会报错,以下是报错的源码
if app_name and not namespace:
raise ValueError('Must specify a namespace if specifying app_name.')

一般来说,同一应用下的不同实例应该具有相同的应用命名空间,但是,这并不意味着不同应用可以使用相同的实例命名空间,因为实例命名空间在你所有项目中都是唯一的。

问题: 另外在添加命名空间 namespace时可能会出现以下这个问题:

'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.

解决方案为:

在对应的app应用的urls.py中添加app_name = '[应用名称]'如下

from django.conf.urls import url
from . import views
app_name = 'users'
# users为当前应⽤用的名称
urlpatterns = [
url('^$', views.index),
url('^(\d+)/$', views.detail),
]

三、url反向解析实例

在我们的django项目中通常App,目录结构就可以如下daily_fresh_demo

daily_fresh_demo 
 |----daily_fresh_demo
    |----__init__.py
    |----settings.py
    |----urls.py
    |----wsgi.py
  |----df_cart #对商品购物⻋车管理理
|---- migrations # 迁移⽂文件⽬目录
|---- admin.py
|---- apps.py
|---- models.py
|---- test.py
|---- urls.py
|---- views.py
|---- __init__.py
  |----df_goods  #商品以及后台管理理
...
  |----df_user #⽤用户管理理
...
  |----df_order #订单管理理
...
  |----templates
     |index.html

1、路由分发:

daily_fresh_demo/daily_fresh_demo/urls.py
from django.contrib import admin

from django.urls import path

from django.conf.urls import url, include
urlpatterns = [
path('admin/', admin.site.urls),
url(r'^goods/', include('df_goods.urls', namespace='df_goods')), # 添
加实例例命名空间
url(r'^user/', include('df_user.urls', namespace='df_user')),
url(r'^cart/', include('df_cart.urls', namespace='df_cart')),
url(r'^order/', include('df_order.urls', namespace='df_order')),
]

根据路由分发到各个相应的app中。并添加实例命名空间


2、子路由

daily_fresh_demo/df_goods/urls.py
from django.conf.urls import url
from . import views
app_name = 'df_goods' # 应⽤用命名空间
urlpatterns = [
url('^index/$', views.index, name="index"),
]

df_goods中的路由,添加应⽤命名空间。并在url函数中添加name属性。

3、视图函数

daily_fresh_demo/df_goods/views.py
from django.shortcuts import render, reverse
def index(request):
print(reverse("df_goods:index")) # 利利⽤用reverse函数反向解析url
  # 打印结果为/goods/index/
return render(request, 'index.html')

4、静态文件index.html

daily_fresh_demo/templates/index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<a href="/goods/index">硬链接</a>
<a href="{% url "df_goods:index" %}">软链接</a>
</body>
</html>

5、结果

静态文件中index.html的url解析结果如下

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<a href="/goods/index">硬链接</a>
<a href="/goods/index/">软链接</a> # 软编码通过解析后得到的结果与硬编码⼀一致
</body>
</html>

总结:这样一来通过命名空间,无论在templates文件中有多庞大的url地址映射,只要使用url软编码,在更改路由系统的时候,都能自动生成。而如果使用硬链接硬编码,就只能在views.py和静态文件中逐个修改url地址,不仅耗费时间,更容易产生错误。

javaee

python

web

ui

cloud

test

c

netmarket

pm

Linux

movies

robot

uids

北京校区

    14天免费试学

    基础班入门课程限时免费

    申请试学名额

    15天免费试学

    基础班入门课程限时免费

    申请试学名额

    15天免费试学

    基础班入门课程限时免费

    申请试学名额

    15天免费试学

    基础班入门课程限时免费

    申请试学名额

    20天免费试学

    基础班入门课程限时免费

    申请试学名额

    8天免费试学

    基础班入门课程限时免费

    申请试学名额

    20天免费试学

    基础班入门课程限时免费

    申请试学名额

    5天免费试学

    基础班入门课程限时免费

    申请试学名额

    0天免费试学

    基础班入门课程限时免费

    申请试学名额

    12天免费试学

    基础班入门课程限时免费

    申请试学名额

    5天免费试学

    基础班入门课程限时免费

    申请试学名额

    5天免费试学

    基础班入门课程限时免费

    申请试学名额

    10天免费试学

    基础班入门课程限时免费

    申请试学名额