Skip to content

路由层 URLConf

路由的作用,是决定“一个请求该交给哪个视图处理”。

浏览器访问网站时,请求到达的只是一个 URL,例如:

  • /
  • /login/
  • /article/12/

Django 必须知道:这些地址分别该交给哪段 Python 代码去处理。这件事就是路由在做。

本节目标

  • 理解路由层的作用
  • 学会使用 path() 配置基础路由
  • 学会接收 URL 参数
  • 理解路径转换器
  • 理解 include() 做分层路由
  • 理解重定向和命名路由的基础概念

为什么需要路由

如果没有路由,Django 就不知道:

  • /users/ 应该执行哪个视图
  • /articles/ 应该执行哪个视图
  • /login/ 应该执行哪个视图

所以路由本质上是一套“地址分发规则”。

一个最基础的路由示例

项目 urls.py

python
from django.contrib import admin
from django.urls import path
from . import views

urlpatterns = [
    path("admin/", admin.site.urls),
    path("hello/", views.hello),
]

视图:

python
from django.http import HttpResponse


def hello(request):
    return HttpResponse("你好,Django")

访问:

text
http://127.0.0.1:8000/hello/

页面显示:

text
你好,Django

这就是一个最基础的 URL 到视图的绑定过程。

path() 是什么意思

最常见的路由写法就是:

python
path("hello/", views.hello)

它的含义是:

  • 当访问 hello/
  • 就调用 views.hello

所以你可以先把 path() 理解成:

  • 一条地址匹配规则

urlpatterns 是什么

python
urlpatterns = [
    ...
]

它是 Django 路由规则的列表。

你可以把它理解成:

  • 整个项目的“地址规则清单”

根路径和普通路径

首页

python
path("", views.home)

这里的空字符串表示网站根路径,也就是:

text
/

普通路径

python
path("about/", views.about)

对应:

text
/about/

URL 参数

很多页面不是固定路径,而是带参数的。

例如文章详情页:

text
/article/12/

这里的 12 通常就是文章编号。

路由写法:

python
path("article/<int:article_id>/", views.article_detail)

视图写法:

python
from django.http import HttpResponse


def article_detail(request, article_id):
    return HttpResponse(f"文章编号是:{article_id}")

访问:

text
/article/12/

页面显示:

text
文章编号是:12

这说明 URL 中的参数已经被 Django 自动传给视图了。

路径转换器

路由参数里常见的转换器有:

  • str
  • int
  • slug
  • uuid

str

默认字符串。

int

只能匹配整数。

slug

常用于文章别名、短字符串标识。

uuid

常用于 UUID 类型标识。

路径转换器的作用,是让 URL 参数更有约束。

为什么路径转换器重要

例如:

python
path("article/<int:article_id>/", ...)

就表示:

  • 这里只接受整数

如果访问:

text
/article/abc/

它不会匹配成功。

这能帮助你减少无效请求和异常情况。

路由分层:include()

项目一大之后,不可能把所有路由都堆在一个 urls.py 里。

这时候通常会按 app 拆分。

项目主路由:

python
from django.urls import path, include

urlpatterns = [
    path("users/", include("users.urls")),
]

然后 users/urls.py

python
from django.urls import path
from . import views

urlpatterns = [
    path("login/", views.login_view),
    path("register/", views.register_view),
]

这样最终访问路径会变成:

  • /users/login/
  • /users/register/

为什么要拆路由

因为大项目的地址会越来越多。

拆分之后的好处是:

  • 结构更清晰
  • 各 app 边界更明确
  • 更容易维护

命名路由

除了直接写路径,Django 还支持给路由起名字。

python
path("login/", views.login_view, name="login")

这表示:

  • 这条路由的名字叫 login

好处是:

  • 后面模板和代码中可以通过名字引用路由
  • 不必到处手写固定路径字符串

零基础阶段先知道这个概念即可。

重定向

有时候视图并不是直接返回页面,而是跳转到另一个地址。

python
from django.shortcuts import redirect


def old_page(request):
    return redirect("/new-page/")

这表示访问旧地址时,自动跳到新地址。

静态资源和业务路由的区别

你后面会接触这些资源:

  • 图片
  • CSS
  • JavaScript

这些和普通业务页面路由不是一回事。

例如:

  • /login/ 是业务页面路由
  • /static/style.css 是静态资源访问路径

零基础阶段你先知道这是两类不同东西即可。

一个完整小案例

主路由:

python
from django.urls import path
from . import views

urlpatterns = [
    path("", views.home),
    path("course/", views.course_list),
    path("course/<int:course_id>/", views.course_detail),
]

视图:

python
from django.http import HttpResponse


def home(request):
    return HttpResponse("首页")


def course_list(request):
    return HttpResponse("课程列表页")


def course_detail(request, course_id):
    return HttpResponse(f"课程编号:{course_id}")

访问结果:

  • / -> 首页
  • /course/ -> 课程列表页
  • /course/3/ -> 课程编号:3

这个例子已经把:

  • 普通路由
  • 根路径
  • 带参数路由

串起来了。

常见错误

1. 路由写了,但视图没导入

这会直接报错。

2. 访问地址和路由规则不一致

例如路由写的是:

python
path("hello/", ...)

却访问成别的路径,就不会匹配成功。

3. 参数写了,但视图函数没接收

如果路由里写了:

python
<int:article_id>

视图函数也必须接对应参数。

4. 所有路由都堆在一个文件里

项目一大之后会很难维护。

练习题

练习 1

写一个路由,让访问 /hello/ 时返回一句欢迎语。

练习 2

写一个首页路由 /

练习 3

写一个详情页路由 /article/<int:id>/,并把 id 显示出来。

练习 4

尝试给一个路由加 name 参数。

练习 5

自己解释:

  • 路由到底解决什么问题
  • 为什么项目大了要用 include() 拆分路由

本节小结

路由层的本质,就是把不同 URL 请求分发给正确的视图处理。

你最重要的收获应该是:

  • 会写最基础的 path()
  • 知道根路径和普通路径怎么配
  • 会接收 URL 参数
  • 理解路径转换器
  • 知道大项目中路由为什么要拆分

只要这一层理解清楚,后面 Django 的页面、详情页、接口和模块结构就都能顺着搭起来。

Built with VitePress.