Django 2.0 路由 path 语法详解:从 url 到 path 的迁移与转化器应用

桃夭
桃夭
发布时间:2026-10-13 | 2人浏览过
原创

本文深入解析 Django 2.0 引入的 path 路由语法,对比旧版 url 函数的差异。详细讲解内置转化器(str, int, slug, uuid, path)的使用方法及自定义转化器的实现步骤,涵盖注册、类型转换与反向解析。同时提供从 Django 1.x 迁移至 2.0 的代码改写示例,并说明 re_path 在复杂正则场景下的保留用法,帮助开发者掌握新版路由配置的最佳实践。

Django 2.0 路由 path 语法详解

9月23日,Django 发布了 2.0a1 版本,这是一个特性冻结(feature freeze)版本。若无意外,2.0 正式版将不再增加新功能,按以往规律预计于 12 月发布。

备注:Django 2.0 已于 12 月 2 日正式发布(链接)。

Django 2.0 是一个里程碑版本,移除了对 Python 2.7 的支持,最低要求 Python 3.4 以上,建议直接使用 3.5 或更高版本。

在 Django 2.0 的新特性文档中,主要列出了三项更新:

更简洁的 URL 路由语法(Simplified URL routing syntax)。

Admin 应用针对移动设备的优化改进(Mobile-friendly contrib.admin)。

支持 SQL 开窗表达式(Window expressions)。

首个特性主要应用于动态路由定义。Django 2.0 代码实现中,核心变化是新增了 django.urls.path 函数,它提供了一种更简洁、易读的路由语法。例如,旧版本的代码写法如下:


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

在新版本中,上述代码可以改写为:


path('articles/<int:year>/', views.year_archive),

新语法支持类型转换。在上述示例中,year_archive 视图函数接收到的 year 参数将直接变为整数类型,而非字符串。

如果你熟悉 Flask 框架,会发现这种 Variable-Rules 语法在形式和功能上与之类似。

问题引入与解决思路

一、问题引入

以下是 Django 1.x 版本的一段典型代码:


 from django.conf.urls import url

def year_archive(request, year):
  year = int(year) # convert str to int
  # Get articles from database

def detail_view(request, article_id):
  pass

def edit_view(request, article_id):
  pass

def delete_view(request, article_id):
  pass

urlpatterns = [
  url('articles/(?P<year>[0-9]{4})/', year_archive),
  url('article/(?P<article_id>[a-zA-Z0-9]+)/detail/', detail_view),
  url('articles/(?P<article_id>[a-zA-Z0-9]+)/edit/', edit_view),
  url('articles/(?P<article_id>[a-zA-Z0-9]+)/delete/', delete_view),
]

针对这段代码,我们可以思考两个问题:

第一个问题是,year_archive 函数中的 year 参数原本是字符串类型,需要手动转换为整数。虽然 year=int(year) 不会抛出 TypeError 或 ValueError 异常,但能否让 Django 自动完成这一转换步骤?

第二个问题是,三个路由中的 article_id 在业务逻辑中表示同一字段,且使用了相同的正则表达式。然而,你需要编写三次代码。如果后续 article_id 的规则发生变化,必须同时修改三处代码。是否存在一种方法,只需修改一处即可生效?

在 Django 2.0 中,使用 path 函数可以解决上述两个问题。

path 使用示例与规则

二、使用示例

这是一个简单的配置示例:


 from django.urls import path

from . import views

urlpatterns = [
  path('articles/2003/', views.special_case_2003),
  path('articles/<int:year>/', views.year_archive),
  path('articles/<int:year>/<int:month>/', views.month_archive),
  path('articles/<int:year>/<int:month>/<slug>/', views.article_detail),
]

基本规则如下:

  • 使用尖括号 (<>) 从 URL 中捕获值。
  • 捕获值中可以包含一个转化器类型(converter type),例如使用 <int:name> 来捕获一个整数变量。如果没有指定转化器,默认匹配任何字符串,包括包含 / 字符的字符串。
  • 无需在路由字符串前添加前导斜杠。

以下是根据 Django 2.0 官方文档整理的示例分析表:

请求URL 匹配项 视图函数调用形式
/articles/2005/03/ 第3个 views.month_archive(request, year=2005, month=3)
/articles/2003/ 第1个 views.special_case_2003(request)
/articles/2003 无 -
/articles/2003/03/building-a-django-site/ 第4个 views.article_detail(request, year=2003, month=3, slug=”building-a-django-site”)

内置 path 转化器

三、path 转化器

文档原文称为 Path converters,此处暂译为转化器。

Django 默认支持以下 5 个转化器:

  • str:匹配除了路径分隔符(/)之外的非空字符串,这是默认形式。
  • int:匹配正整数,包含 0。
  • slug:匹配由字母、数字、横杠和下划线组成的字符串。
  • uuid:匹配格式化的 UUID,例如 075194d3-6885-417e-a8a8-6c931e272f00。
  • path:匹配任何非空字符串,包含路径分隔符。

自定义转化器的定义与注册

四、自定义转化器

4.1 定义

对于复杂或需要复用的场景,可以定义自定义转化器。转化器是一个类或接口,需满足以下三点要求:

  • regex 类属性,类型为字符串。
  • to_python(self, value) 方法:value 是由类属性 regex 匹配到的字符串,该方法返回具体的 Python 变量值,供 Django 传递给对应的视图函数。
  • to_url(self, value) 方法:与 to_python 相反,value 是一个具体的 Python 变量值,该方法返回其字符串形式,通常用于 URL 反向解析。

首先查看默认的 IntConverter 和 StringConverter 的实现方式:


 class IntConverter:
  regex = '[0-9]+'

  def to_python(self, value):
    return int(value)

  def to_url(self, value):
    return str(value)


class StringConverter:
  regex = '[^/]+'

  def to_python(self, value):
    return value

  def to_url(self, value):
    return value

第二个例子是一个自定义的 4 位年份转化器。


 class FourDigitYearConverter:
  regex = '[0-9]{4}'

  def to_python(self, value):
    return int(value)

  def to_url(self, value):
    return '%04d' % value

4.2 注册

使用 register_converter 将其注册到 URL 配置中:


 from django.urls import register_converter, path

from . import converters, views

register_converter(converters.FourDigitYearConverter, 'yyyy')

urlpatterns = [
  path('articles/2003/', views.special_case_2003),
  path('articles/<yyyy:year>/', views.year_archive),
  ...
]

正则表达式与 re_path 的使用

五、使用正则表达式

如果上述 path 和 converters 仍无法满足需求,可以使用正则表达式,此时应使用 django.urls.re_path 函数。

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

之前的示例代码也可以改写为:


 from django.urls import path, re_path

from . import views

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

这段代码与之前的代码实现了基本功能,但存在以下区别:

  • 这里的匹配更加严格,例如 year=10000 在此处将无法匹配。
  • 传递给视图函数的变量均为字符串类型,这一点与旧版 url 一致。

无命名分组

一般来说,不建议使用无命名分组的方式,因为这可能引入歧义甚至导致错误。

Import 路径变动与代码迁移

六、Import 变动

django.urls.path 可视为 django.conf.urls.url 的增强形式。

为了方便使用,其引用路径也发生了变化。请注意 urls 包路径的变更,它不再是 conf 的子包,目前与 views、conf 一样,被视为 Django 的核心组件。

1.X 2.0 备注
- django.urls.path 新增,url的增强版
django.conf.urls.include django.urls.include 路径变更
django.conf.urls.url django.urls.re_path 异名同功能,url不会立即废弃

七、代码改写

将“问题引入”一节的代码使用新的 path 函数改写如下:


 from django.urls import path, register_converter
from django.urls.converters import SlugConverter

class FourDigitYearConverter:
  regex = '[0-9]{4}'

  def to_python(self, value):
    return int(value)

  def to_url(self, value):
    return '%04d' % value

register_converter(SlugConverter, 'article_id')
register_converter(FourDigitYearConverter, 'year')

def year_archive(request, year):
  print(type(year)) # <class 'int'>
  # Get articles from database

def detail_view(request, article_id):
  pass

def edit_view(request, article_id):
  pass

def delete_view(request, article_id):
  pass

urlpatterns = [
  path('articles/<year:year>/', year_archive),
  path('article/<article_id:article_id>/detail/', detail_view),
  path('articles/<article_id:article_id>/edit/', edit_view),
  path('articles/<article_id:article_id>/delete/', delete_view),
]

八、总结

第一,目前从路由(URL)到视图(View)的流程可概括为四个步骤:

1. URL 匹配 2. 正则捕获 3. 变量类型转换 4. 视图调用

与之前版本相比,Django 2.0 增加了“变量类型转换”这一步骤。

第二,新的 path 语法可以解决以下场景:

  • 类型自动转换
  • 公用正则表达式复用

了解更多:https://www.jb51.net/article/165591.htm

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表