Python
URL 路由与视图
发布于 2026年7月22日
URL 路由与视图
本篇聚焦 Django 的请求入口。你将理解 URL 如何匹配视图、视图如何读取请求,以及什么时候返回 HTML、JSON、重定向或错误响应。
完成后,你应该能独立设计清晰、可维护且可反向解析的 URL。
一、一次请求经历了什么
浏览器访问 http://127.0.0.1:8000/messages/12/ 时,Django 会依次执行:
- 创建
HttpRequest对象。 - 从项目根
urls.py开始匹配路径。 - 将路径参数传给目标 View。
- View 执行业务逻辑并返回
HttpResponse。 - 中间件处理响应,最终发送给浏览器。
最小视图如下:
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)
命名空间能避免不同应用都使用 detail、create 时发生冲突。
五、读取请求数据
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_GET、require_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_name和name反向解析 URL。 - 能读取路径参数、查询参数和表单数据。
- 知道删除等有副作用的操作不应使用 GET。
- 能正确返回模板、JSON、重定向和 404。
上一篇:第一个 Django 应用 | 下一篇:模型、ORM 与数据库迁移