浏览知识库目录

Python

URL 路由与视图

URL 路由与视图

本篇聚焦 Django 的请求入口。你将理解 URL 如何匹配视图、视图如何读取请求,以及什么时候返回 HTML、JSON、重定向或错误响应。

完成后,你应该能独立设计清晰、可维护且可反向解析的 URL。


一、一次请求经历了什么

浏览器访问 http://127.0.0.1:8000/messages/12/ 时,Django 会依次执行:

  1. 创建 HttpRequest 对象。
  2. 从项目根 urls.py 开始匹配路径。
  3. 将路径参数传给目标 View。
  4. View 执行业务逻辑并返回 HttpResponse
  5. 中间件处理响应,最终发送给浏览器。

最小视图如下:

from django.http import HttpResponse


def hello(request):
    return HttpResponse("Hello Django")

视图必须返回响应对象,不能只返回字符串、字典或模型对象。


二、path() 的基本写法

notes/urls.py

from django.urls import path

from . import views

app_name = "notes"

urlpatterns = [
    path("", views.message_list, name="list"),
    path("create/", views.message_create, name="create"),
    path("<int:pk>/", views.message_detail, name="detail"),
]

path() 常用参数:

  • route:要匹配的路径,不以 / 开头。
  • view:匹配成功后调用的视图。
  • kwargs:传给视图的额外参数,较少使用。
  • name:URL 名称,用于反向解析。

常用路径转换器:

转换器 示例 匹配内容
str <str:slug> 非空字符串,不含 /
int <int:pk> 正整数
slug <slug:slug> 字母、数字、横线、下划线
uuid <uuid:id> UUID
path <path:file_path> 可包含 / 的路径

三、拆分项目路由与应用路由

项目根路由只负责分发,不应堆积全部业务 URL。

mysite/urls.py

from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path("admin/", admin.site.urls),
    path("messages/", include("notes.urls")),
]

这样 /messages/12/ 会先匹配 messages/,再把剩余的 12/ 交给 notes.urls


四、URL 命名空间与反向解析

不要在模板或 Python 代码中硬编码 /messages/create/。路径调整后,所有硬编码都要修改。

在应用路由中定义:

app_name = "notes"

模板中使用:

<a href="{% url 'notes:create' %}">新增留言</a>
<a href="{% url 'notes:detail' message.pk %}">{{ message.name }}</a>

Python 中使用:

from django.shortcuts import redirect
from django.urls import reverse

url = reverse("notes:detail", kwargs={"pk": 12})
return redirect("notes:detail", pk=12)

命名空间能避免不同应用都使用 detailcreate 时发生冲突。


五、读取请求数据

def inspect_request(request):
    method = request.method
    keyword = request.GET.get("q", "")
    name = request.POST.get("name", "")
    user = request.user
    agent = request.headers.get("User-Agent", "")
  • request.GET:查询字符串,例如 ?q=django
  • request.POST:表单提交的数据。
  • request.FILES:上传的文件。
  • request.user:当前用户,需要认证中间件。
  • request.session:当前会话。
  • request.headers:HTTP 请求头。
  • request.body:原始请求体,处理 JSON 时可能用到。

不要直接相信请求数据。表单页面优先交给 Form 校验,API 优先交给 DRF Serializer 校验。


六、常用响应方式

1. 返回文本

from django.http import HttpResponse


def health(request):
    return HttpResponse("ok", content_type="text/plain")

2. 渲染模板

from django.shortcuts import render


def message_list(request):
    return render(request, "notes/list.html", {"title": "留言列表"})

3. 返回 JSON

from django.http import JsonResponse


def status(request):
    return JsonResponse({"status": "ok"})

4. 重定向

from django.shortcuts import redirect


def old_page(request):
    return redirect("notes:list")

5. 返回 404

from django.shortcuts import get_object_or_404, render

from .models import Message


def message_detail(request, pk):
    message = get_object_or_404(Message, pk=pk)
    return render(request, "notes/detail.html", {"message": message})

get_object_or_404() 比手动捕获 DoesNotExist 更适合常规详情页。


七、限制请求方法

删除操作不能通过普通 GET 链接触发,否则搜索引擎或预加载工具可能误删数据。

from django.shortcuts import get_object_or_404, redirect
from django.views.decorators.http import require_POST

from .models import Message


@require_POST
def message_delete(request, pk):
    message = get_object_or_404(Message, pk=pk)
    message.delete()
    return redirect("notes:list")

常用装饰器还有 require_GETrequire_http_methods(["GET", "POST"])


八、自定义错误页面

生产环境关闭 DEBUG 后,可以提供:

templates/
  400.html
  403.html
  404.html
  500.html

错误页应简洁,不暴露堆栈、配置、数据库信息或密钥。


九、常见问题

NoReverseMatch

检查 URL 名称、命名空间和参数数量。例如路由需要 pk,模板却没有传值。

路径一直 404

检查末尾斜杠、include() 前缀和路由顺序。更具体的路由应放在可能吞掉它的宽泛路由前。

POST 返回 403

HTML 表单内应有 {% csrf_token %},并确认请求来自正确域名。


十、本篇检查清单

  • 能解释项目路由与应用路由的职责。
  • 能使用 app_namename 反向解析 URL。
  • 能读取路径参数、查询参数和表单数据。
  • 知道删除等有副作用的操作不应使用 GET。
  • 能正确返回模板、JSON、重定向和 404。

上一篇:第一个 Django 应用 | 下一篇:模型、ORM 与数据库迁移