2.1 创建 App
Django 项目由多个 App 组成,每个 App 聚焦一个功能领域。用 startapp 生成骨架:
$ python manage.py startapp blog
blog/
├── __init__.py
├── admin.py # 后台注册
├── apps.py # App 配置
├── models.py # 数据模型
├── views.py # 视图逻辑
├── tests.py
└── migrations/
创建后必须在 settings.py 里注册:
INSTALLED_APPS = [
# ... 内置 App
"blog", # 或 "blog.apps.BlogConfig"
]
- URLconf(URL configuration)
- Django 的路由表,用 Python 列表
urlpatterns把 URL 模式映射到视图。每个 App 通常有自己的urls.py。 - path()
- 定义一条路由:
path(route, view, name=...)。route 用简洁的路径转换器语法,如<int:pk>。 - re_path()
- 用正则表达式匹配 URL,适合 path 转换器表达不了的复杂模式。
- include()
- 把某个前缀下的路由委派给 App 的 urls.py,实现路由的模块化组合。
- 路径转换器(Path Converter)
str/int/slug/uuid/path。捕获的值作为关键字参数传给视图。- 命名 URL(Named URL)
- 给路由起
name,在代码/模板中用名字反查真实 URL,避免硬编码路径。 - reverse()
- 根据 URL 名字与参数反向生成 URL 字符串,是「命名 URL」在 Python 侧的用法。
2.2 第一个视图函数
# blog/views.py
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello, 古法编程 · Django 博客首页")
def detail(request, post_id):
return HttpResponse(f"你正在看第 {post_id} 篇文章")
2.3 App 内的 urls.py
# blog/urls.py(需手动创建)
from django.urls import path
from . import views
app_name = "blog" # 命名空间
urlpatterns = [
path("", views.index, name="index"),
path("post/<int:post_id>/", views.detail, name="detail"),
]
2.4 用 include 挂载到根路由
# mysite/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path("admin/", admin.site.urls),
path("blog/", include("blog.urls")),
]
现在 /blog/ 命中 index,/blog/post/5/ 命中 detail 并把 5 作为 post_id 传入。
2.5 路径转换器
| 转换器 | 匹配 | 示例 |
|---|---|---|
| str | 非空非斜杠字符串(默认) | <str:slug> |
| int | 零或正整数 | <int:pk> |
| slug | 字母数字连字符 | <slug:title> |
| uuid | UUID 格式 | <uuid:id> |
| path | 含斜杠的字符串 | <path:rest> |
2.6 re_path 正则路由
from django.urls import re_path
urlpatterns = [
re_path(r"^archive/(?P<year>[0-9]{4})/$", views.archive),
]
优先用 path
path 转换器可读性远高于正则。仅当需要精确控制格式(如四位年份、特定后缀)时才用 re_path。
2.7 命名 URL 与 reverse
from django.urls import reverse
from django.shortcuts import redirect
# 反查 URL(带命名空间 app_name:name)
url = reverse("blog:detail", kwargs={"post_id": 5})
# => "/blog/post/5/"
# 视图里重定向到命名 URL
def go(request):
return redirect("blog:index")
在模板中同理,用 {% url %} 标签:
<a href="{% url 'blog:detail' post.id %}">{{ post.title }}</a>
永远不要硬编码 URL
把 /blog/post/5/ 写死在模板里,一旦路由结构变动就得全站搜索替换。始终用命名 URL + reverse/{% url %},改路由零成本。
2.8 小结与下一步
- 用
startapp拆功能单元,记得在INSTALLED_APPS注册。 - URLconf 用
path/re_path映射,用include组合 App 路由。 - 路径转换器捕获参数并传给视图;命名 URL +
reverse/{% url %}消除硬编码。 - 下一章进入 Model 与 ORM——用 Python 类定义数据库,享受迁移与 QuerySet。