第一章:Django 入门与环境搭建
1.1 Django 简介与特点
| 方法/概念名称 | 语法/说明 | 用途 | 代码示例 | 注意事项 |
|---|
| MTV 架构 | Model-Template-View | Django 的设计模式,分离数据、展示与逻辑 | 无具体代码 | 区别于 MVC,View 相当于 Controller,Template 是视图展示 |
| 高层抽象 | 内置功能丰富 | 快速开发 Web 应用,避免重复造轮子 | 无具体代码 | 包含 ORM、Admin、Auth 等开箱即用组件 |
| 可扩展性 | 支持插件与第三方包 | 灵活集成新功能 | pip install django-extensions | 可通过 pip 安装大量社区贡献工具 |
| 安全性 | 防 CSRF、SQL 注入等 | 保护应用安全 | {% csrf_token %} 在表单中自动启用 | 默认启用常见安全机制,减少人为错误 |
| 管理后台 | 自动生成 admin 界面 | 快速实现数据管理 | python manage.py createsuperuser | 无需额外开发即可拥有功能完整的后台系统 |
1.2 安装 Django 与版本管理
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| pip install | pip install django | 安装最新版 Django | pip install django | 建议在虚拟环境中执行 |
| 指定版本安装 | pip install django==4.2.7 | 安装特定版本 Django | pip install django==3.2 | 版本需符合项目或教程要求 |
| 查看版本 | python -m django --version | 验证 Django 是否安装成功 | python -m django --version | 若报错说明未正确安装或路径问题 |
| 虚拟环境创建 | python -m venv myenv | 创建独立 Python 环境 | python -m venv venv | 推荐每个项目使用独立虚拟环境 |
| 激活虚拟环境(Windows) | myenv\Scripts\activate | 激活虚拟环境 | venv\Scripts\activate | 激活后命令行前缀会显示环境名 |
| 激活虚拟环境(macOS/Linux) | source myenv/bin/activate | 激活虚拟环境 | source venv/bin/activate | 使用 source 命令加载环境变量 |
| 退出虚拟环境 | deactivate | 退出当前虚拟环境 | deactivate | 恢复使用系统默认 Python 环境 |
1.3 创建第一个 Django 项目
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| django-admin startproject | django-admin startproject 项目名 | 创建新的 Django 项目 | django-admin startproject mysite | 可在任意目录执行 |
| manage.py startproject | python manage.py startproject 项目名 | 通过管理脚本创建项目 | python manage.py startproject blog . | 加点表示在当前目录创建,不嵌套 |
| 项目命名规则 | 小写字母、下划线、不能是 Python 关键字 | 避免命名冲突 | my_project, blog_site | 不要用 class、def 等关键字作为项目名 |
| 目录切换 | cd 项目目录 | 进入项目根目录 | cd mysite | 后续操作通常在此目录下进行 |
1.4 项目结构解析
| 文件/目录名 | 路径 | 用途 | 示例内容 | 注意事项 |
|---|
| manage.py | 项目根目录 | Django 命令行工具 | python manage.py runserver | 不要修改此文件,用于执行各类管理命令 |
| settings.py | 项目名/settings.py | 项目配置文件 | DEBUG = True, INSTALLED_APPS | 包含数据库、应用、静态文件等核心设置 |
| urls.py | 项目名/urls.py | 根 URL 配置 | urlpatterns = [...] | 所有 URL 的入口,可 include 其他应用路由 |
| wsgi.py | 项目名/wsgi.py | WSGI 部署接口 | 用于生产环境服务器通信 | 通常无需修改 |
| asgi.py | 项目名/asgi.py | ASGI 异步接口(Django 3.0+) | 支持 WebSocket 等异步协议 | 用于异步部署场景 |
| __init__.py | 项目名/__init__.py | 标识为 Python 包 | 可为空 | 确保 Django 模块可被导入 |
1.5 启动开发服务器
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| runserver | python manage.py runserver | 启动内置开发服务器 | python manage.py runserver | 默认监听 127.0.0.1:8000 |
| 指定端口 | python manage.py runserver 8080 | 更改服务器端口 | python manage.py runserver 8080 | 适用于端口被占用时 |
| 指定 IP | python manage.py runserver 0.0.0.0:8000 | 允许外部访问 | python manage.py runserver 0.0.0.0:8000 | 用于局域网调试,注意安全 |
| 自动重载 | 开启状态下修改代码自动重启 | 提高开发效率 | 无需手动命令 | 开发服务器默认启用 |
| 关闭服务器 | Ctrl + C | 终止服务器进程 | 在终端按 Ctrl+C | 正常关闭,避免端口占用问题 |
| 检查配置 | python manage.py check | 验证项目配置正确性 | python manage.py check | 可在启动前运行以排查错误 |
第二章:URL 路由与视图
2.1 URL 路由配置(urls.py)
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| path | path(route, view, kwargs=None, name=None) | 定义简洁 URL 路由 | path('home/', views.home, name='home') | route 以路径形式书写,不使用正则 |
| re_path | re_path(route, view, kwargs=None, name=None) | 使用正则表达式定义复杂路由 | re_path(r'^article/(\d+)/$', views.article_detail) | 需导入 re_path,支持捕获组传参 |
| include | include('app.urls') | 引入应用级 URL 配置 | path('blog/', include('blog.urls')) | 实现模块化,避免主路由臃肿 |
| URLPattern | 自定义类继承 | 高级用法,自定义路由逻辑 | 一般不直接使用 | 框架底层机制,开发者较少直接操作 |
| app_name | app_name = 'blog' | 设置应用命名空间 | 在应用 urls.py 中定义 | 配合命名 URL 使用,避免冲突 |
2.2 视图函数(View Functions)
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| 视图函数定义 | def view_name(request, *args, **kwargs): | 处理 HTTP 请求并返回响应 | def index(request): return HttpResponse("Hello") | 第一个参数必须是 request |
| HttpResponse | HttpResponse(content, content_type, status) | 返回 HTTP 响应 | return HttpResponse("OK", status=200) | 最基础响应类,用于返回字符串内容 |
| render | render(request, template_name, context) | 渲染模板并返回 | return render(request, 'index.html', {'data': data}) | 自动使用 RequestContext |
| redirect | redirect(to, *args, **kwargs) | 执行 HTTP 重定向 | return redirect('home') 或 redirect('/home/') | to 可为 URL 名称或绝对路径 |
| HttpResponseRedirect | HttpResponseRedirect('/url/') | 显式返回 302 重定向 | return HttpResponseRedirect('/success/') | 与 redirect 功能类似,但需手动指定 URL |
2.3 类视图(Class-Based Views)基础
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| as_view | ClassName.as_view() | 将类视图转换为可调用视图函数 | path('home/', MyView.as_view()) | URL 路由中必须调用此方法 |
| dispatch | def dispatch(self, request, *args, **kwargs) | 分发请求到对应处理方法 | return super().dispatch(request, ...) | 可用于权限检查或日志记录 |
| get | def get(self, request, *args, **kwargs) | 处理 GET 请求 | def get(self, request): ... | 类视图中处理 GET 的标准方法 |
| post | def post(self, request, *args, **kwargs) | 处理 POST 请求 | def post(self, request): ... | 接收表单提交等数据 |
| http_method_not_allowed | def http_method_not_allowed(...) | 处理不支持的 HTTP 方法 | 默认返回 405 状态码 | 可重写自定义行为 |
2.4 路由参数传递(路径与查询参数)
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| 路径参数 | path('item/<int:id>/', views.detail) | 从 URL 路径提取参数 | path('user/<str:username>/') | 支持类型转换:str, int, slug, uuid 等 |
| 查询参数获取 | request.GET.get('key') | 获取 URL 查询字符串参数 | value = request.GET.get('page', 1) | GET 是类字典对象,使用 get 安全获取 |
| 正则捕获组 | re_path(r'^page/(\d+)/$', ...) | 使用正则提取参数 | re_path(r'^tag/(\w+)/$', views.by_tag) | 参数按顺序传入视图 |
| 命名捕获组 | re_path(r'^article/(?P<year>\d{4})/$', ...) | 正则命名捕获 | 参数以关键字传入视图 | 提高可读性,推荐使用 |
| 多参数传递 | path('a/<int:x>/b/<str:y>/') | 同时传递多个路径参数 | 视图接收 x 和 y 两个参数 | 顺序和名称需匹配 |
2.5 命名 URL 与 reverse 解析
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| reverse | reverse(viewname, args=None, kwargs=None) | 根据名称反向生成 URL | url = reverse('detail', args=[1]) | 常用于视图中重定向 |
| resolve | resolve('/some/url/') | 根据 URL 反解析视图信息 | match = resolve('/blog/1/') | 返回 ResolverMatch 对象 |
{% url %} | {% url 'view_name' arg1 arg2 %} | 模板中生成命名 URL | <a href="{% url 'home' %}">Home</a> | 推荐在模板中使用,避免硬编码 |
| 命名空间引用 | {% url 'app:detail' id=1 %} | 使用应用命名空间 | 需在 include 时定义 app_name | 避免不同应用间 URL 名称冲突 |
| redirect | redirect('view_name', arg) | 结合命名 URL 进行重定向 | return redirect('update', pk=obj.id) | 比硬编码 URL 更灵活安全 |
第三章:模板系统(Templates)
3.1 模板创建与加载机制
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| render | render(request, 'template.html') | 加载并渲染模板 | return render(request, 'list.html') | Django 自动在 TEMPLATES DIR 中查找 |
| loader.get_template | get_template('name.html') | 手动加载模板对象 | t = loader.get_template('index.html') | 返回 Template 实例,可多次渲染 |
| Context | Context({'key': value}) | 创建模板上下文 | c = Context({'name': 'Alice'}) | 通常由 render 自动处理 |
| Template | Template("Hello {{ name }}") | 创建字符串模板 | t = Template("Hi {{ user }}") | 用于动态生成模板内容 |
| 模板目录配置 | 'DIRS': [BASE_DIR / 'templates'] | 设置模板搜索路径 | 在 settings.py 中配置 | 推荐集中存放模板文件 |
3.2 模板语法:变量、标签、过滤器
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| 变量输出 | {{ variable }} | 显示变量值 | {{ user.name }} | 自动 HTML 转义防止 XSS |
| 过滤器 | {{ value|filter:arg }} | 变换变量输出格式 | {{ text|truncatechars:30 }} | 可链式使用多个过滤器 |
| if 标签 | {% if condition %}...{% endif %} | 条件判断 | {% if user.is_authenticated %}...{% endif %} | 支持 elif 和 else |
| for 标签 | {% for item in list %}...{% endfor %} | 循环遍历 | {% for post in posts %}...{% endfor %} | 可用 forloop 变量获取循环信息 |
| with 标签 | {% with total=10 %}...{% endwith %} | 创建临时变量 | {% with name=user.get_name %}...{% endwith %} | 减少重复计算或调用 |
3.3 模板继承与块(extends, block)
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| extends | {% extends "base.html" %} | 继承父模板 | 必须是模板第一行内容 | 实现页面结构复用 |
| block | {% block title %}...{% endblock %} | 定义可替换块 | {% block content %}{% endblock %} | 子模板中重写该块内容 |
| block.super | {{ block.super }} | 包含父模板块内容 | {% block title %}{{ block.super }} - Blog{% endblock %} | 在原有内容基础上追加 |
| include | {% include "nav.html" %} | 嵌入其他模板片段 | 用于复用组件如导航栏 | 不涉及继承关系 |
| 重写块 | {% block content %}新内容{% endblock %} | 子模板覆盖父块 | 必须在 extends 之后定义 | 可部分保留或完全替换 |
3.4 静态文件处理(CSS, JS, Images)
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| load static | {% load static %} | 加载静态文件标签 | {% load static %} | 必须先加载才能使用 static |
| static | {% static 'path/to/file' %} | 获取静态文件 URL | <link href="{% static 'css/style.css' %}"> | 开发环境自动服务,生产需配置 |
| STATIC_URL | STATIC_URL = '/static/' | 静态文件 URL 前缀 | 在 settings.py 中设置 | 通常为 /static/ |
| STATICFILES_DIRS | 配置额外静态文件目录 | STATICFILES_DIRS = [BASE_DIR / "static"] | 告诉 Django 哪些目录包含静态文件 | 开发时收集静态文件的来源 |
| collectstatic | python manage.py collectstatic | 收集所有静态文件到统一目录 | 用于生产环境部署 | 将分散的静态文件复制到 STATIC_ROOT |
3.5 模板上下文处理器
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| RequestContext | render(request, ...) 自动使用 | 自动包含处理器变量 | return render(request, 'index.html') | render 已默认使用 |
| 自定义处理器 | def processor(request): return {...} | 添加全局模板变量 | def site_name(request): return {'SITE_NAME': 'MySite'} | 函数需接收 request 并返回 dict |
| 常用内置处理器 | django.contrib.auth.context_processors.auth | 提供用户、权限信息 | 可在模板中使用 user, perms | 默认启用 |
| 关闭处理器 | 从 TEMPLATES['OPTIONS']['context_processors'] 移除 | 禁用特定处理器 | 减少上下文开销 | 仅在确定不需要时关闭 |
| 多处理器协作 | 多个处理器返回的 dict 合并 | 构建完整上下文 | 每个处理器负责一部分数据 | 避免键名冲突 |
第四章:模型(Models)与数据库操作
4.1 模型定义与字段类型
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| CharField | models.CharField(max_length=100) | 存储短文本字符串 | name = models.CharField(max_length=50) | 必须指定 max_length |
| TextField | models.TextField() | 存储长文本 | content = models.TextField() | 无长度限制,适合文章内容 |
| IntegerField | models.IntegerField() | 存储整数 | age = models.IntegerField() | 不支持小数 |
| FloatField | models.FloatField() | 存储浮点数 | price = models.FloatField() | 注意精度问题 |
| BooleanField | models.BooleanField() | 存储布尔值 | active = models.BooleanField(default=True) | 可设 default 值 |
| DateTimeField | models.DateTimeField() | 存储日期时间 | created = models.DateTimeField(auto_now_add=True) | auto_now 每次保存更新,auto_now_add 创建时设置 |
| ForeignKey | models.ForeignKey(OtherModel, on_delete=...) | 外键关系 | author = models.ForeignKey(User, on_delete=models.CASCADE) | 必须指定 on_delete 行为 |
| EmailField | models.EmailField() | 验证并存储邮箱 | email = models.EmailField() | 自动格式验证 |
| ImageField | models.ImageField(upload_to='images/') | 存储图片文件 | avatar = models.ImageField(upload_to='avatars/') | 需安装 Pillow 库 |
4.2 数据库迁移(migrate, makemigrations)
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| makemigrations | python manage.py makemigrations | 生成数据库迁移文件 | python manage.py makemigrations | 检测模型变更并创建迁移脚本 |
| migrate | python manage.py migrate | 应用迁移到数据库 | python manage.py migrate | 执行 SQL 更新数据库结构 |
| showmigrations | python manage.py showmigrations | 查看迁移状态 | 显示已应用和未应用的迁移 | 帮助诊断问题 |
| sqlmigrate | python manage.py sqlmigrate app 0001 | 显示迁移对应的 SQL | 查看实际执行的 SQL 语句 | 用于调试和学习 |
| —fake | python manage.py migrate --fake | 标记迁移为已应用但不执行 | 用于同步迁移状态 | 仅在特殊情况下使用 |
| 回退迁移 | python manage.py migrate app_name 0001 | 回退到指定迁移版本 | 撤销后续迁移 | 谨慎操作,可能丢失数据 |
4.3 ORM 基本操作:增删改查
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| create | Model.objects.create(**kwargs) | 创建并保存对象 | User.objects.create(name='Alice') | 一步完成实例化和保存 |
| save | obj.save() | 保存对象(新建或更新) | user.name = 'Bob'; user.save() | 可触发信号和自定义逻辑 |
| get | Model.objects.get(**kwargs) | 获取单个对象 | user = User.objects.get(id=1) | 无结果或多个结果均抛异常 |
| filter | Model.objects.filter(**kwargs) | 查询多个对象 | users = User.objects.filter(active=True) | 返回 QuerySet,可链式调用 |
| update | QuerySet.update(**kwargs) | 批量更新 | User.objects.filter(...).update(active=False) | 不调用 save(),不触发信号 |
| delete | obj.delete() 或 QuerySet.delete() | 删除对象 | user.delete() | 根据 on_delete 策略处理关联对象 |
4.4 查询集(QuerySet)方法详解
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| all | Model.objects.all() | 获取全部对象 | posts = Post.objects.all() | 返回惰性查询集 |
| exclude | QuerySet.exclude(**kwargs) | 排除匹配对象 | Post.objects.exclude(status='draft') | 逻辑为 NOT |
| order_by | QuerySet.order_by('field') | 排序结果 | Post.objects.order_by('-created') | - 表示降序 |
| values | QuerySet.values(*fields) | 返回字典列表 | Post.objects.values('title', 'author') | 轻量数据提取 |
| values_list | QuerySet.values_list('field', ...) | 返回元组列表 | Post.objects.values_list('id', flat=True) | flat=True 用于单字段展平 |
| distinct | QuerySet.distinct() | 去除重复记录 | Post.objects.distinct('author') | 依据字段去重 |
| count | QuerySet.count() | 统计数量 | Post.objects.filter(...).count() | 比 len() 更高效 |
| first / last | QuerySet.first() | 获取首个/末个对象 | Post.objects.filter(...).first() | 可能返回 None |
| exists | QuerySet.exists() | 判断是否存在 | if Post.objects.filter(...).exists(): | 比 count() > 0 更快 |
| select_related | QuerySet.select_related() | 预加载外键关联 | Post.objects.select_related('author') | 减少 N+1 查询,一对一/多对一 |
4.5 模型关系:ForeignKey, OneToOneField, ManyToManyField
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| ForeignKey | models.ForeignKey(To, on_delete=...) | 多对一关系 | Post 关联 User 外键 | on_delete 必填(CASCADE, SET_NULL 等) |
| OneToOneField | models.OneToOneField(To, ...) | 一对一关系 | Profile 关联 User | 如用户与个人资料 |
| ManyToManyField | models.ManyToManyField(To) | 多对多关系 | Book 关联 Author | 自动创建中间表 |
| add | m2m_field.add(obj) | 多对多添加关联 | book.authors.add(author) | 可传多个对象 |
| remove | m2m_field.remove(obj) | 移除多对多关联 | book.authors.remove(author) | 从关系中删除 |
| clear | m2m_field.clear() | 清空所有关联 | book.authors.clear() | 不删除对象本身 |
| set | m2m_field.set([obj_list]) | 批量设置关联 | book.authors.set([a1, a2]) | 替换现有关系 |
| related_name | ForeignKey(..., related_name='posts') | 自定义反向关系名称 | user.posts.all() | 避免默认的 modelname_set |
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| db_table | db_table = 'custom_name' | 指定数据库表名 | db_table = 'blog_posts' | 覆盖默认表名 app_model |
| ordering | ordering = ['field'] | 默认排序字段 | ordering = ['-created'] | 查询时自动应用 |
| verbose_name | verbose_name = '单数名' | 人类可读的单数名称 | verbose_name = '文章' | 用于 Admin 和文档 |
| verbose_name_plural | verbose_name_plural = '复数名' | 人类可读的复数名称 | verbose_name_plural = '文章列表' | 覆盖默认复数形式 |
| unique_together | unique_together = [('a', 'b')] | 字段组合唯一约束 | 确保 a 和 b 的组合唯一 | 已逐渐被 UniqueConstraint 替代 |
| indexes | indexes = [models.Index(...)] | 自定义数据库索引 | indexes = [Index(fields=['title'])] | 提升查询性能 |
4.7 自定义模型 Manager
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| objects | Model.objects | 默认管理器 | User.objects.all() | 所有模型默认拥有 |
| 自定义 Manager | class MyManager(models.Manager): | 创建专用查询接口 | class PublishedManager(models.Manager): ... | 继承 models.Manager |
| get_queryset | def get_queryset(self): | 重写查询集 | return super().get_queryset().filter(status='published') | 控制 manager 返回的数据集 |
| 自定义方法 | def method(self): | 添加查询方法 | def recent(self): return self.filter(...) | 可在 manager 上直接调用 |
| 多管理器 | objects = models.Manager(); published = PublishedManager() | 为模型添加多个管理器 | 可在不同场景使用不同 manager | 只有一个是默认 manager |
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| Form | class MyForm(forms.Form): | 定义普通表单 | name = forms.CharField(max_length=100) | 不直接关联模型 |
| ModelForm | class MyModelForm(forms.ModelForm): | 基于模型生成表单 | class Meta: model = Post; fields = '__all__' | 自动生成字段,减少重复 |
| Meta 内部类 | class Meta: model, fields | 配置 ModelForm 行为 | fields = ['title', 'content'] 或 exclude = [...] | 必须指定 model |
| 字段重写 | field = forms.CharField(...) | 自定义字段属性 | title = forms.CharField(widget=forms.Textarea) | 覆盖 ModelForm 自动生成的字段 |
| 自定义字段 | field = forms.FieldType() | 添加非模型字段 | captcha = forms.CharField() | 用于验证码等附加数据 |
5.2 表单验证机制
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| clean | def clean(self): | 验证整个表单数据 | if pwd != confirm: raise ValidationError | 在所有字段验证后调用 |
| clean_<field> | def clean_<fieldname>(self): | 验证特定字段 | def clean_email(self): ... | 方法名格式为 clean_<字段名> |
| ValidationError | raise ValidationError('错误信息') | 抛出验证错误 | from django.core.exceptions import ValidationError | 中断验证流程 |
| 内置验证器 | validators=[MinLengthValidator(8)] | 添加字段级验证器 | password = forms.CharField(validators=[validate_password]) | 可组合多个验证器 |
| required | field = forms.CharField(required=True) | 设置字段是否必填 | 默认为 True | False 表示可为空 |
5.3 在视图中使用表单
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| GET 处理 | if request.method == 'GET': | 显示空表单 | form = MyForm() | 通常用于首次访问页面 |
| POST 处理 | elif request.method == 'POST': | 处理提交数据 | form = MyForm(request.POST) | 区分请求方法 |
| is_valid | if form.is_valid(): | 验证表单数据 | 数据合法后可访问 cleaned_data | 必须先调用 |
| save | obj = form.save() | 保存表单数据(ModelForm) | obj = form.save(commit=False) | commit=False 可延迟保存 |
| cleaned_data | form.cleaned_data['field'] | 获取清洗后的数据 | title = form.cleaned_data['title'] | 仅在 is_valid() 后可用 |
5.4 表单模板渲染
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| as_p | {{ form.as_p }} | 以段落形式渲染 | 每个字段包裹在 <p> 中 | 简单布局 |
| as_table | {{ form.as_table }} | 以表格形式渲染 | 字段作为表格行 | 适合对齐 |
| as_ul | {{ form.as_ul }} | 以列表形式渲染 | 每个字段为 <li> 项 | 常用于表单列表 |
| 手动渲染 | {{ form.field }} | 逐个字段控制 | {{ form.title }} {{ form.title.errors }} | 灵活性最高 |
| CSRF 标签 | {% csrf_token %} | 防止跨站请求伪造 | 必须在 POST 表单中包含 | 安全必需 |
5.5 文件上传处理
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| FileField | models.FileField(upload_to='files/') | 模型中定义文件字段 | 在模型中使用 | 需配置 MEDIA 设置 |
| ImageField | models.ImageField(...) | 专用图像字段 | 需安装 Pillow | 自动验证图像格式 |
| form.is_multipart | form.is_multipart() | 判断表单是否含文件 | if form.is_multipart(): ... | 决定是否用 request.FILES |
| request.FILES | request.FILES['file'] | 获取上传文件 | form = MyForm(request.POST, request.FILES) | 必须同时传 POST 和 FILES |
| MEDIA_URL | MEDIA_URL = '/media/' | 用户访问媒体文件的 URL 前缀 | 在 settings.py 中设置 | 开发环境需配置 URL |
| MEDIA_ROOT | MEDIA_ROOT = BASE_DIR / 'media' | 媒体文件存储的绝对路径 | 服务器上实际文件位置 | 生产环境需静态服务器服务 |
第六章:用户认证与权限
6.1 用户模型(User)与认证系统
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| create_user | User.objects.create_user(username, email, password) | 创建普通用户(自动哈希密码) | User.objects.create_user('alice', 'a@b.com', 'pass123') | 不应直接设置 password 字段 |
| authenticate | authenticate(request, username, password) | 验证用户凭据 | user = authenticate(username='alice', password='pass') | 验证成功返回 User 对象,失败返回 None |
| login | login(request, user) | 登录用户并创建会话 | login(request, user) | 需在 authenticate 成功后调用 |
| logout | logout(request) | 登出用户并清除会话 | logout(request) | 不接收参数,清除 request.session 数据 |
| get_user | get_user(request) | 从会话获取用户对象 | user = get_user(request) | 常用于中间件或自定义逻辑 |
6.2 登录、登出视图
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| LoginView | from django.contrib.auth.views import LoginView | 内置登录视图 | 可继承自定义 | 默认使用 registration/login.html |
| LogoutView | from django.contrib.auth.views import LogoutView | 内置登出视图 | 配置 URL 即可 | 登出后跳转到 LOGIN_REDIRECT_URL |
| login_required | @login_required | 装饰器限制访问 | @login_required def view(...): ... | 未登录用户重定向到登录页 |
| next 参数 | ?next=/target/ | 登录后跳转目标 | 登录成功后自动跳转原请求页面 | 安全验证目标 URL 是否本站 |
| 自定义登录表单 | class CustomAuthForm(AuthenticationForm): | 扩展默认登录表单 | 可添加字段或修改验证逻辑 | 需在视图中指定 form_class |
6.3 用户注册实现
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| UserCreationForm | forms.UserCreationForm | 内置用户注册表单 | 继承并自定义字段 | 包含用户名、密码1、密码2 |
| UserChangeForm | forms.UserChangeForm | 用于修改用户信息 | 管理后台默认使用 | 更适合用户资料编辑 |
| set_password | user.set_password('new_pass') | 安全设置用户密码 | user.set_password(raw_password) | 自动哈希,不应直接赋值 |
| save(commit=False) | form.save(commit=False) | 暂不保存到数据库 | 可先修改对象再保存 | 常用于注册时添加额外数据 |
| send_mail | from django.core.mail import send_mail | 发送注册确认邮件 | send_mail(subject, msg, from, to) | 需配置邮件后端 |
6.4 权限与组管理
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| Permission | 模型权限(add, change, delete, view) | 控制模型操作权限 | user.has_perm('blog.add_post') | 自动生成四种基本权限 |
| Group | Group.objects.create(name='Editor') | 用户分组管理权限 | 将权限分配给组,用户加入组 | 简化权限管理 |
| user_passes_test | @user_passes_test(test_func) | 基于函数的权限控制 | @user_passes_test(lambda u: u.is_staff) | test_func 接收 user 返回布尔值 |
| has_perm | user.has_perm('app.action_model') | 检查用户是否有权限 | if request.user.has_perm('polls.change_choice'): ... | 权限字符串格式为 app_label.action_model |
| assign_perm | user.user_permissions.add(perm) | 为用户分配权限 | user.user_permissions.add(permission) | 可直接操作权限关系 |
6.5 装饰器控制访问(@login_required 等)
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| login_required | @login_required | 要求用户已登录 | @login_required def my_view(...): ... | 未登录跳转至 LOGIN_URL |
| permission_required | @permission_required('polls.change_poll') | 要求特定权限 | 可设置 raise_exception=True | 无权限返回 403 或重定向 |
| user_passes_test | @user_passes_test(lambda u: u.is_superuser) | 自定义条件测试 | 更灵活的访问控制 | 可实现复杂逻辑 |
| method_decorator | method_decorator(dec, name) | 将函数装饰器用于类视图 | @method_decorator(login_required, name='dispatch') | 类视图中使用函数装饰器 |
| staff_member_required | @staff_member_required | 仅限管理员访问 | 装饰管理功能视图 | 基于 is_staff 字段 |
第七章:高级视图与通用视图
7.1 类视图进阶:ListView, DetailView, CreateView, UpdateView, DeleteView
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| ListView | class PostList(ListView): model = Post | 显示对象列表 | template_name = 'list.html' | 默认上下文 object_list |
| DetailView | class PostDetail(DetailView): model = Post | 显示单个对象详情 | context_object_name = 'post' | 默认使用 pk 或 slug 查找 |
| CreateView | class PostCreate(CreateView): model = Post; fields = '__all__' | 创建新对象 | success_url = reverse_lazy('list') | 自动处理表单显示与保存 |
| UpdateView | class PostUpdate(UpdateView): model = Post | 更新现有对象 | 需提供 pk 或 slug | 表单预填充原数据 |
| DeleteView | class PostDelete(DeleteView): model = Post | 删除对象确认页 | success_url = '/success/' | 需用户确认,防止误删 |
7.2 混合类(Mixins)使用
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| LoginRequiredMixin | class View(LoginRequiredMixin, ...): | 要求登录才能访问 | 必须放在继承列表左侧 | 比装饰器更适合类视图 |
| PermissionRequiredMixin | class View(PermissionRequiredMixin, ...): | 要求特定权限 | permission_required = 'polls.change_poll' | 无权限返回 403 |
| UserPassesTestMixin | class View(UserPassesTestMixin, ...): | 自定义测试逻辑 | def test_func(self): return self.request.user.is_staff | test_func 返回布尔值 |
| SuccessMessageMixin | class View(SuccessMessageMixin, CreateView): | 添加成功消息 | success_message = "创建成功!" | 需配合 messages 框架使用 |
| MultipleObjectMixin | 用于 ListView 等 | 提供分页、查询集管理 | 通常已内置使用 | 基础混合类 |
7.3 自定义视图逻辑(get_context_data, form_valid 等)
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| get_context_data | def get_context_data(self, **kwargs): | 添加额外上下文数据 | context['extra'] = Value; return context | 必须调用 super() 获取默认数据 |
| form_valid | def form_valid(self, form): | 处理有效表单提交 | return super().form_valid(form) | 可在此添加额外逻辑(如发邮件) |
| form_invalid | def form_invalid(self, form): | 处理无效表单提交 | 可记录日志或修改响应 | 默认重新显示表单 |
| get_queryset | def get_queryset(self): | 自定义查询集 | return Post.objects.filter(active=True) | 控制视图获取的数据范围 |
| dispatch | def dispatch(self, request, *args, **kwargs): | 分发请求前处理 | return super().dispatch(request, ...) | 可用于权限检查或日志 |
7.4 重定向与 HTTP 响应控制
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| HttpResponseRedirect | HttpResponseRedirect('/url/') | 返回 302 重定向 | return HttpResponseRedirect('/success/') | 明确指定目标 URL |
| redirect | redirect('view_name', arg) | 便捷重定向函数 | return redirect('detail', pk=obj.id) | 支持 URL 名称和参数 |
| reverse_lazy | reverse_lazy('view_name') | 延迟反向解析 URL | success_url = reverse_lazy('home') | 用于类属性定义,避免导入时求值 |
| HttpResponsePermanentRedirect | 返回 301 重定向 | SEO 友好,永久重定向 | 搜索引擎会更新索引 | 用于 URL 永久变更 |
| HttpResponseNotFound | HttpResponseNotFound() | 返回 404 状态码 | raise Http404 或 return response | 也可使用 raise Http404 |
第八章:中间件(Middleware)
8.1 中间件概念与执行流程
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| __init__ | def __init__(self, get_response): | 初始化中间件 | self.get_response = get_response | 每个请求前执行一次 |
| __call__ | def __call__(self, request): | 处理请求并返回响应 | response = self.get_response(request); return response | 核心处理逻辑 |
| process_request | def process_request(self, request): | 在视图前处理请求 | 可返回 None 或 HttpResponse | 返回 HttpResponse 则短路后续 |
| process_response | def process_response(self, request, response): | 在响应后处理响应 | 必须返回 HttpResponse 对象 | 所有情况下都会调用 |
| 执行顺序 | MIDDLEWARE 列表顺序 | 决定中间件执行流程 | 上:request,下:response | request 从上到下,response 从下到上 |
8.2 常用内置中间件
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| SecurityMiddleware | 'django.middleware.security.SecurityMiddleware' | 提供安全防护(如 HSTS) | 防止 XSS、点击劫持等 | 生产环境强烈建议启用 |
| SessionMiddleware | 'django.contrib.sessions.middleware.SessionMiddleware' | 启用会话支持 | 依赖数据库或缓存后端 | 认证系统的基础 |
| CommonMiddleware | 'django.middleware.common.CommonMiddleware' | 处理常见任务(如 URL 重写) | 可配置 APPEND_SLASH | 自动处理尾部斜杠 |
| CsrfViewMiddleware | 'django.middleware.csrf.CsrfViewMiddleware' | 防护 CSRF 攻击 | 表单需 {% csrf_token %} | 关键安全组件 |
| AuthenticationMiddleware | 'django.contrib.auth.middleware.AuthenticationMiddleware' | 将用户附加到 request | request.user 可用 | 必须在 SessionMiddleware 之后 |
8.3 自定义中间件编写
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| 函数式中间件 | def simple_middleware(get_response): ... | 旧式函数中间件 | def middleware(request): ... | 现推荐类形式 |
| 类中间件 | class SimpleMiddleware: | 新式类中间件 | 必须实现 __init__ 和 __call__ | 更结构化 |
| process_view | def process_view(self, request, view_func, view_args, view_kwargs): | 在调用视图前执行 | 可返回 None 或 HttpResponse | 可用于权限检查 |
| process_exception | def process_exception(self, request, exception): | 视图抛出异常时调用 | 可返回 HttpResponse 拦截异常 | 用于自定义错误页面 |
| process_template_response | def process_template_response(self, request, response): | 处理 TemplateResponse 时调用 | 可修改 response.template_name | 用于动态模板选择 |
第九章:RESTful API 开发(可选:结合 Django REST Framework)
注:以下基于 Django REST Framework (DRF)
9.1 API 设计原则
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| REST 原则 | 使用标准 HTTP 方法 | 设计无状态 API 接口 | GET: 查询, POST: 创建, PUT: 更新, DELETE: 删除 | 遵循资源导向 |
| 状态码 | 200 OK, 201 Created, 400 Bad Request, 404 Not Found | 正确表达操作结果 | 创建成功返回 201 | 提高 API 可理解性 |
| 版本控制 | /api/v1/resource/ | 避免 API 变更影响客户端 | 可通过 URL、Header 控制 | 推荐 URL 路径版本 |
| JSON 格式 | 使用 JSON 作为数据交换格式 | 统一请求与响应结构 | DRF 默认使用 JSON | 易于前后端解析 |
| HATEOAS | 包含相关资源链接 | 实现超媒体驱动 | 响应中包含 next, previous 链接 | 高级 REST 特性 |
9.2 使用 DRF Serializers
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| Serializer | class MySerializer(serializers.Serializer): | 定义序列化规则 | field = serializers.CharField() | 手动定义所有字段 |
| ModelSerializer | class MyModelSerializer(serializers.ModelSerializer): | 基于模型自动生成 | class Meta: model = Post; fields = '__all__' | 减少重复代码 |
| create | def create(self, validated_data): | 处理反序列化创建 | return MyModel.objects.create(**validated_data) | 自定义对象创建逻辑 |
| update | def update(self, instance, validated_data): | 处理反序列化更新 | instance.name = validated_data.get('name'); return instance | 自定义更新逻辑 |
| validate | def validate_<field>(self, value): | 字段级验证 | if value < 0: raise serializers.ValidationError("负数无效") | 类似表单 clean_<field> |
9.3 API Views 与 ViewSets
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| APIView | class PostList(APIView): | DRF 基础视图类 | 重写 get, post 等方法 | 完全控制逻辑 |
| GenericAPIView | class PostList(GenericAPIView): | 通用 API 视图 | 配合 mixins 使用 | 提供 queryset, serializer_class 等属性 |
| ListCreateAPIView | class PostList(ListCreateAPIView): | 列表与创建组合 | 自动处理 GET 和 POST | 减少代码量 |
| ViewSet | class PostViewSet(viewsets.ModelViewSet): | 视图集,路由自动映射 | 需配合 routers 使用 | 更简洁的 REST 实现 |
| ModelViewSet | class PostViewSet(viewsets.ModelViewSet): | 完整 CRUD 操作 | 包含 list, create, retrieve, update, destroy | 最常用 ViewSet |
9.4 认证与权限控制在 API 中的应用
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| BasicAuthentication | 'rest_framework.authentication.BasicAuthentication' | HTTP 基本认证 | 简单但不安全,建议配合 HTTPS | 用户名密码 Base64 编码 |
| TokenAuthentication | 'rest_framework.authentication.TokenAuthentication' | Token 认证机制 | 每用户生成唯一 Token | 需安装 drf-authtoken |
| SessionAuthentication | 'rest_framework.authentication.SessionAuthentication' | 基于会话认证 | 适合浏览器客户端 | 与 Django 认证系统集成 |
| IsAuthenticated | 'rest_framework.permissions.IsAuthenticated' | 仅允许认证用户访问 | permission_classes = [IsAuthenticated] | 常用权限类 |
| IsOwnerOrReadOnly | 自定义权限类 | 作者可编辑,他人只读 | 继承 BasePermission 实现 | 保护用户数据 |
第十章:部署与性能优化
10.1 生产环境配置(DEBUG, ALLOWED_HOSTS)
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| DEBUG = False | DEBUG = False | 关闭调试模式 | 绝对不可在生产开启 | 开启会暴露敏感信息 |
| ALLOWED_HOSTS | ALLOWED_HOSTS = ['example.com', 'www.example.com'] | 限制可服务的域名 | 防止 HTTP Host 头攻击 | 必须正确配置 |
| SECRET_KEY | SECRET_KEY = '生产专用密钥' | 加密签名密钥 | 从环境变量读取 | 切勿提交到代码仓库 |
| DATABASES | 配置生产数据库(如 PostgreSQL) | 使用稳定数据库 | 推荐 PostgreSQL 或 MySQL | 避免 SQLite 用于生产 |
| CSRF_TRUSTED_ORIGINS | CSRF_TRUSTED_ORIGINS = ['https://example.com'] | 信任的跨域来源 | 配合 HTTPS 使用 | 防止 CSRF 攻击 |
10.2 静态文件收集(collectstatic)
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| collectstatic | python manage.py collectstatic | 收集所有静态文件 | 生产部署前执行 | 将分散文件复制到统一目录 |
| STATIC_ROOT | STATIC_ROOT = '/var/www/static/' | 指定收集目标目录 | Nginx 将服务此目录 | 必须设置 |
| STATIC_URL | STATIC_URL = '/static/' | 静态文件 URL 前缀 | 模板中使用 {% static %} | 与 STATIC_ROOT 区分 |
| WhiteNoise | 'whitenoise.middleware.WhiteNoiseMiddleware' | 在 Django 中服务静态文件 | 简化部署,适合小流量 | 可替代 Nginx 静态服务 |
| CDN 集成 | 将 STATIC_URL 指向 CDN 地址 | 加速静态资源加载 | STATIC_URL = 'https://cdn.example.com/static/' | 提升全球访问速度 |
10.3 使用 Gunicorn + Nginx 部署
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| Gunicorn | gunicorn myproject.wsgi:application | WSGI HTTP 服务器 | 可设置 worker 数量 | Django 生产常用服务器 |
| Nginx | server { listen 80; location / { proxy_pass http://127.0.0.1:8000; } } | 反向代理与静态文件服务 | 处理并发、SSL、缓存 | 作为前端服务器 |
| systemd 服务 | 创建 .service 文件 | 管理 Gunicorn 进程 | 开机自启、崩溃重启 | 生产环境推荐 |
| Supervisor | 配置 supervisord | 进程监控工具 | 监控多个 Django 实例 | 比 systemd 更灵活 |
| 环境变量 | export DJANGO_SETTINGS_MODULE=prod_settings | 配置运行环境 | 使用 python-decouple 或 django-environ | 避免硬编码配置 |
10.4 日志配置与错误监控
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| LOGGING 配置 | LOGGING = {...} in settings.py | 配置日志记录器 | 定义 handlers, loggers, formatters | 生产环境必须启用 |
| logging.debug/info/error | logger.info('Message') | 记录不同级别日志 | import logging; logger = logging.getLogger(__name__) | 调试、信息、错误分类 |
| Sentry | 集成 Sentry SDK | 错误跟踪与报警 | 实时监控异常 | 推荐用于生产环境 |
| 日志轮转 | TimedRotatingFileHandler | 按时间分割日志文件 | 避免单个文件过大 | 易于管理和归档 |
| 500 错误页面 | 500.html 模板 | 自定义服务器错误页面 | 改善用户体验 | 需 DEBUG=False 时生效 |