JavaEE鸿蒙应用开发HTML&JS+前端Python+大数据开发人工智能开发电商视觉设计软件测试新媒体+短视频直播运营产品经理集成电路应用开发(含嵌入式)Linux云计算+运维开发C/C++拍摄剪辑+短视频制作PMP项目管理认证电商运营Go语言与区块链大数据PHP工程师Android+物联网iOS.NET

Django框架基础之路由详解

来源:黑马程序员

浏览41971人

2019.08.30

中路由的作用:

其本质是URL与该URL要调用的视图函数之间的映射,就是为告诉Django对客户端发过来的某个URL应该调用执行哪一段逻辑代码

路由基本的配置:

1.jpg

细说url函数的第一个参数:

2.jpg

注意点:

1. urlpatterns列表中的元素按照书写顺序从上往下逐一匹配正则表达式,一旦匹配成功则不再继续。

2. 当请求匹配urlpatterns完所有元素后也未匹配成功,就会向客户端返回404.

3. 若要从URL中捕获一个值,只需要在 / / 里放置一对圆括号,并写上对应的正则匹配即可(分组匹配)。

4. 不需要添加一个前导的反斜杠,因为每个URL 默认前面就会有反斜杠。例如,应该是^articles 而不是 ^/articles

5. 每个正则表达式前面的'r' 是可选的但是建议加上。让正则字符串中任何字符都不被转义,保留原始。

路由正则表达式结尾是否要加 '/' 说明:

 from django.conf.urls import url
 from app01 import views
 
 urlpatterns = [
  url(r'^index/$', views.index),  # 结尾加'/'  
  url(r'^test$', views.test),  # 结尾不加 '/'
 ]

例如:

测试1:访问http://127.0.0.1:8000/indexhttp://127.0.0.1:8000/index/ 结果都是成功的,因为当访问http://127.0.0.1:8000/index时会自动做301重定向到http://127.0.0.1:8000/index/

测试2:访问http://127.0.0.1:8000/test是成功的, http://127.0.0.1:8000/test/就会失败了

那么到底是什么原因?怎么会这样呢?

 # 如路由中结尾有'/' 但请求中的url结尾没有加'/'匹配时是否在URL中附加尾部斜杠 True添加,False不添加
 APPEND_SLASH=True  # Djangoglobal_settings的默认配置

没有命名的正则表达式组:

 # 将加圆括号的正则表达式匹配到的内容当做位置参数自动传递给对应的视图函数
 
 # 路由层
 url(r'^test/(d+)/',views.test),  # 匹配一个或多个数字
 
 # 视图层
 def test(request, num):   # num接收到从路由括号圆括号内,相应正则表达式中匹配的值
     print(num)
     return HttpResponse('test')

有命名的正则表达式组:

Python的正则表达式中,分组命名正则表达式组的语法是(?P<name>pattern),其中name是组的名称,pattern是要匹配的模式

 # 将加圆括号的正则表达式匹配到的内容当做关键字参数自动传递给对应的视图函数
 
 # 路由层
 url(r'^test/(?P<year>d+)/',views.test),  # 匹配一个或多个数字
 
 # 视图层
 def test(request, year):  # 此处的形参名一定要和正则组命名一致
     print(year)
     return HttpResponse('test')

下面是代码是 使用有命名的正则表达式组重写:

 from django.conf.urls import url
 
 from . import views
 
 urlpatterns = [
     url(r'^articles/2003/$', views.special_case_2003),
     url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
     url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
     url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail),
 ]

这个实现与前面的示例完全相同,只有一个细微的差别:捕获的值作为关键字参数而不是位置参数传递给视图函数。

在实际应用中,使用有命名的正则表达式组会更加明晰且不容易产生参数顺序问题的错误 —— 你可以在你的视图函数定义中重新安排参数的顺序。 当然,这些好处是以简洁为代价的;一些开发人员发现命名组语法丑陋而且太冗长。

注意:

无名正则表达式组和有名正则表达式组不能混着用!!!

 # 要么都不命名
 url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
 # 要命名都要命名
 url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
 # 不能这样混着用,报错提示缺少必传位置参数
 url(r'^articles/(?P<year>[0-9]{4})/([0-9]{2})/$', views.month_archive),

正则表达式组捕获的参数都是字符串类型:

每个捕获的参数都作为一个普通的Python 字符串传递给视图,无论正则表达式使用的是什么匹配方式。 例如,

 url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),

传递给views.year_archive()year参数将是一个字符串,不是整数,即使[0-9]{4}只匹配整数字符串

指定视图参数的默认值:

在这里给大家说一个方便的小技巧是指定视图参数的默认值。 URLconf 和视图的示例:

 # URLconf
 from django.conf.urls import url
 
 from . import views
 
 urlpatterns = [
     url(r'^blog/$', views.page),
     url(r'^blog/page(?P<num>[0-9]+)/$', views.page),
 ]
 
 # View (in blog/views.py)
 def page(request, num="1"):
     # 此处省略若干行代码...

在上面的例子中:

两个URL指向同一个视图views.page

但是第一个不会从URL 中捕获任何值。 如果第一个匹配成功,page() 函数中num将使用默认的参数值"1"

如果第二个模式匹配,page() 将使用正则表达式捕获的num 值。

通过上面例子,你发现了什么呢?

说明我们视图函数中的普通参数变为默认参数后,可以让我们的视图函数变的更灵活,这样我们可以让一个视图函数被多种路由去灵活使用。