codecamp

Django4.0 URL调度器-使用正则表达式

如果路径和转化器语法不能很好的定义你的 URL 模式,你可以可以使用正则表达式。如果要这样做,请使用 ​re_path()​ 而不是 ​path()​ 。

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

这里是先前 ​URLconf ​的一些例子,现在用正则表达式重写一下:

from django.urls import path, re_path

from . import views

urlpatterns = [
    path('articles/2003/', views.special_case_2003),
    re_path(r'^articles/(?P<year>[0-9]{4})/, views.year_archive), 
    re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/, views.month_archive), 
    re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<slug>[\w-]+)/, views.article_detail),
 ]

这实现了与前面示例大致相同的功能,除了:

  • 将要匹配的 URLs 将稍受限制。比如,10000 年将不在匹配,因为 year 被限制长度为4。
  • 无论正则表达式进行哪种匹配,每个捕获的参数都作为字符串发送到视图。

当从使用 ​path()​ 切换到 ​re_path()​ (反之亦然),要特别注意,视图参数类型可能发生变化,你可能需要调整你的视图。

使用未命名的正则表达式组

还有命名组语法,例如 ​(?P<year>[0-9]{4})​ ,你也可以使用更短的未命名组,例如 ​([0-9]{4})​ 。
不是特别推荐这个用法,因为它会更容易在匹配的预期含义和视图参数之间引发错误。

在任何情况下,推荐在给定的正则表达式里只使用一个样式。当混杂两种样式时,任何未命名的组都会被忽略,而且只有命名的组才会传递给视图函数。

嵌套参数

正则表达式允许嵌套参数,Django 将处理它们并传递给视图。当转换时,Django 将试着填充给所有外部捕捉参数,忽略任何嵌套捕捉参数。考虑下面可选的带有页面参数的 URL 模式:

from django.urls import re_path

urlpatterns = [
    re_path(r'^blog/(page-(\d+)/)?, blog_articles),                  # bad
    re_path(r'^comments/(?:page-(?P<page_number>\d+)/)?, comments),  # good
]

两个模式使用嵌套参数,并处理:例如, ​blog/page-2/​ 将匹配给 ​blog_articles​ 并带有2个参数:​page-2/​ 和 ​​。第二个模式为 ​comments ​匹配 ​comments/page-2/​ 并带有设置为2的关键参数 ​page_number ​。这个案例里的外部参数是一个非捕捉参数 (?:...) 。

blog_articles ​视图需要反转最外层捕捉的参数,​page-2/​ 在这里不需要参数,而 ​comments可以在没有参数或 ​page_number值的情况下反转。

嵌套捕捉参数在视图参数和 URL 直接创建一个强耦合,如 ​blog_articles所示:视图接收部分 URL (​page-2/​) 而不只是视图要的值。当反转时这种耦合更明显,因为反转视图我们需要传递一段 URL 而不是 ​page number​。

根据经验,只有当正则表达式需要一个参数但视图忽略它时,才捕捉该视图需要的值并使用非捕捉参数。


Django4.0 URL调度器-注册自定义的路径转换器
Django4.0 URL调度器-URLconf在什么上查找
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

Django4.0 模型和数据库

Django4.0 处理HTTP请求

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }