一、 URL name详解
from django.conf.urls import url
from django.contrib import admin
from calc import views as calc_views
urlpatterns = [
url(r'^add/$', calc_views.add, name='add'),
url(r'^add/(d+)/(d+)/$', calc_views.add2, name='add2'),
url(r'^admin/', admin.site.urls),
]
url(r'^add/$', calc_views.add, name='add'), 这里的 name='add' 是用来干什么的呢?
简单说,name 可以用于在 templates, models, views ……中得到对应的网址,相当于“给网址取了个名字”,只要这个名字不变,网址变了也能通过名字获取到。
模板中可以这样利用name
不带参数的:
{% url 'name' %}
带参数的:参数可以是变量名
{% url 'name' 参数 %}
结合上面的urls.py
不带参数:
<a href="{% url 'add' %}">添加</a>
上面模板经过渲染后的标签是这样的:
<a href="/add/">添加</a>
带参数的:
<a href="{% url 'add2' 4 5 %}">link</a>
经过渲染后:
<a href="/add/4/5/">link</a>
当 urls.py 进行更改,前提是不改 name(这个参数设定好后不要轻易改),获取的网址也会动态地跟着变,比如改成:
url(r'^new_add/(d+)/(d+)/$', calc_views.add2, name='add2'),
注意: add 变成了 new_add,但是后面的
name='add2'
没改,这时{% url 'add2' 4 5 %}
就会渲染对应的网址成/new_add/4/5/
向视图传递额外的参数
url()中允许你传递一个Python字典作为额外的关键字参数给视图函数。
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}),
]
在上面的例子中,对于/blog/2005/请求,Django将调用views.year_archive(request, year='2005', foo='bar')。
注意:命名关键字参数和在字典中传递的额外参数要避免重名。
利用reverse函数反向生成URL
urls.py
from app01 import views as views
urlpatterns = [
url(r'^login/',views.login),
url(r'^index/first/',views.index,name='first'),
]
views.py
from django.shortcuts import render,HttpResponse,redirect
from django.urls import reverse
def login(request):
url = reverse('first')
print(url) # 打印结果:/index/first/
return redirect(url)
def index(request):
return HttpResponse('index/first')
对有参数的url设置name
urls.py:
from django.conf.urls import url
from . import views
urlpatterns = [
#...
url(r'^articles/([0-9]{4})/$', views.year_archive, name='news-year-archive'),
#...
]
模板代码中使用:
<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a> # 注意模版语言的用法,注意参数的传递方法
{# Or with the year in a template context variable: #}
<ul>
{% for yearvar in year_list %}
<li><a href="{% url 'news-year-archive' yearvar %}">{{ yearvar }} Archive</a></li>
{% endfor %}
</ul>
views.py视图函数:
from django.urls import reverse
from django.http import HttpResponseRedirect
def redirect_to_year(request):
# ...
year = 2006
# ...注意参数的传递方法
return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))
二、include路由转发
通常,我们会在每个app里,各自创建一个urls.py路由模块,然后从根路由出发,将app所属的url请求,全部转发到相应的urls.py模块中。
创建两个app:cmdb和openstack,并分别在这两个app目录下创建urls.py文件
from django.conf.urls import url,include
# 需要先导入include函数
from django.contrib import admin
from app01 import views
urlpatterns = [
# url(r'^admin/', admin.site.urls),
url(r'^cmdb/',include('cmdb.urls')),
url(r'^openstack/',include('openstack.urls')),
]
传递额外的参数给include()
参数会传递给include指向的urlconf中的每一行,例如,下面两种URLconf配置方式在功能上完全相同:
配置一:
# main.py
from django.conf.urls import include, url
urlpatterns = [
url(r'^blog/', include('inner'), {'blogid': 3}),
]
# inner.py
from django.conf.urls import url
from mysite import views
urlpatterns = [
url(r'^archive/$', views.archive),
url(r'^about/$', views.about),
]
配置二:
# main.py
from django.conf.urls import include, url
from mysite import views
urlpatterns = [
url(r'^blog/', include('inner')),
]
# inner.py
from django.conf.urls import url
urlpatterns = [
url(r'^archive/$', views.archive, {'blogid': 3}),
url(r'^about/$', views.about, {'blogid': 3}),
]
注意,只有当你确定被include的URLconf中的每个视图都接收你传递给它们的额外的参数时才有意义,否则其中一个以上视图不接收该参数都将导致错误异常。
三、URL命名空间
URL命名空间可以保证反查到唯一的URL。
urls.py
from django.conf.urls import url,include
urlpatterns = [
url(r'^cmdb/',include('cmdb.urls',namespace='cmdb')),
url(r'^openstack/',include('openstack.urls',namespace='openstack')),
]
cmdb/urls.py
from django.conf.urls import url
from cmdb import views
urlpatterns = [
url(r'host/',views.host,name='host'),
]
在模板中使用:
<a href="{% url 'cmdb:host' %}">跳转</a>
在视图中利用reverse()函数反向生成url
from django.shortcuts import render,HttpResponse,redirect
from django.urls import reverse
def host(request):
url = reverse('cmdb:host')
print(url) # 打印结果:/cmdb/host/
return HttpResponse('cmdb.host')
注意:namespace与name在模板文件和视图函数中使用的时候要用冒号分隔,如:“cmdb:host”
四、include()本质
include()函数实际上就是返回一个元组:([], None, None)
第一个元素可以是一个列表,列表中盛放url()子路由配置;
第二个元素是app_name,可以为None;
第三个元素是namespace,需要反向生成url时,可根据需求填写;
所以urls.py也可以这样写:
from django.conf.urls import url
urlpatterns = [
url(r'^openstack/',([],None,None,),
]
直接用一个元组替代include()
如下,直接进行子路由分发:
from django.conf.urls import url,include
from cmdb import views as cviews
from app01 import views
urlpatterns = [
# url(r'^admin/', admin.site.urls),
url(r'^index/',views.index,name='index'),
url(r'^cmdb/',include('cmdb.urls',namespace='cmdb')),
# url(r'^openstack/',include('openstack.urls',namespace='openstack')),
url(r'^openstack/',([
url(r'^host/',cviews.host,name='host'),
url(r'^host/add/',cviews.addhost,name='addhost'),
url(r'^host/(d+)/change',cviews.changehost,name='changehost'),
],None,'openstack')),
]
以上元组中的'openstack',就相当于include()函数的
namespace='openstack'
。
作者:天佑俊辰
链接:https://www.jianshu.com/p/0e5bdc73fcab
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。