web框架学习记录
[TOC]
django
1️⃣ 框架概述
- Django 是一个用 Python 编写的开源 Web 框架。
- 它遵循 MVC/MVT 架构模式(Model-View-Template)。
- 目标是快速开发、安全可靠、可扩展的 Web 应用。
- 官方网站:https://www.djangoproject.com/
2️⃣ 主要特点
- 快速开发
- 内置管理后台(Admin)
- ORM 映射数据库,免写大量 SQL
- 内置表单、认证、会话、缓存支持
- 安全性高
- 自动防止 SQL 注入
- 防止跨站脚本 (XSS)
- 防止跨站请求伪造 (CSRF)
- 提供用户认证和权限管理
- 可扩展性强
- 支持插件和第三方库
- 模块化设计,项目可拆分为多个 App
- 可与 REST API、GraphQL 等接口集成
- 丰富的生态
- 有 Django REST Framework(DRF)支持 API 开发
- Django Channels 支持 WebSocket
- 支持 Celery 异步任务队列
3️⃣ 架构模式
MVT(Model-View-Template)
组件 | 功能 |
---|---|
Model | 数据模型,负责数据库操作(ORM 映射表) |
View | 业务逻辑处理,接收请求,返回响应 |
Template | 前端模板,负责展示 HTML 页面 |
- 类似 MVC:
- Controller 的角色由 View + URL Dispatcher 承担
- Template 对应 View 层的展示部分
4️⃣ 项目结构
一个典型 Django 项目结构:
1 | myproject/ |
5️⃣ 核心组件
- ORM(Object Relational Mapping)
- Python 类映射数据库表
- 支持关系、外键、联合唯一约束、多对多关系
- Admin 管理后台
- 自动生成增删改查后台界面
- 可通过
admin.py
配置显示字段、搜索、过滤
- URL 路由
- 将请求 URL 映射到 View 函数或类
- 支持动态参数和命名空间
- 中间件(Middleware)
- 请求和响应处理链
- 可做认证、日志、压缩、跨域等处理
- 模板系统(Template)
- 渲染 HTML 页面
- 支持模板继承和自定义标签
6️⃣ 应用场景
- Web 应用系统(博客、电商、CMS)
- RESTful API 开发(结合 DRF)
- 后台管理系统
- 数据可视化系统
- 社交平台和微服务
✅ 总结:
- Django 是 Python 最流行的 Web 框架之一
- 提供全栈开发能力(前端模板 + 后端逻辑 + 数据库)
- 特点:快速、安全、可扩展、模块化
- 核心理念:“Don’t repeat yourself(DRY)”
新建项目
库初始化
Django 使用 migrate
命令来初始化数据库。这个命令会应用所有已定义的迁移文件,创建数据库表。
配置数据库
在 settings.py
文件中,配置数据库连接。默认情况下,Django 使用 SQLite 数据库:
1 | # settings.py |
如果你使用其他数据库(如 PostgreSQL、MySQL 等),需要安装相应的数据库驱动并配置连接参数。例如,使用 PostgreSQL:
1 | pip install psycopg2 |
然后在 settings.py
中配置:
1 | DATABASES = { |
多数据配置(进阶)
运行迁移
- 生成迁移文件(根据你定义的模型生成数据库表结构):
1 | python manage.py makemigrations |
运行以下命令来初始化数据库:
1 | python manage.py migrate |
这个命令会创建所有必要的数据库表,包括 Django 自带的用户认证系统表。
清空数据
使用 Django 管理命令
Django 提供了一个 flush
命令,可以清空所有应用的数据。但这个命令会清空整个数据库,而不是特定的应用。如果你只想清空特定应用的数据,可以结合 migrate
命令来实现。
回滚指定应用的迁移:首先,回滚指定应用的迁移,这将删除该应用的所有表。
1
python manage.py migrate myapp zero
这个命令会将
myapp
的迁移回滚到初始状态,删除该应用的所有表。重新应用迁移:然后,重新应用迁移,创建空表。
1
python manage.py migrate myapp
这个命令会重新应用
myapp
的迁移,创建空表
创建管理员用户
使用 createsuperuser
命令创建一个管理员用户:
1 | python manage.py createsuperuser |
运行这个命令后,系统会提示你输入用户名、邮箱和密码。例如:
1 | Username (leave blank to use 'yourusername'): admin |
4. 启动开发服务器
启动 Django 开发服务器,访问项目:
1 | python manage.py runserver |
打开浏览器,访问 http://127.0.0.1:8000/admin
,使用刚才创建的管理员用户登录。
模型定义
主键(Primary Key)
每个 Django 模型默认有一个 id
主键字段:
1 | id = models.AutoField(primary_key=True) |
可以自定义主键:
1 | book_id = models.CharField(max_length=20, primary_key=True) |
主键保证表中每条记录唯一,用于 ORM 查询、关联外键等。
复合主键(Multi-column PK)
Django 不支持原生多列主键。
方法 1(推荐):
给表增加单列主键(id/UUID)。
原来的多列字段加唯一约束:
1
2
3
4
5
6
7
8class A(models.Model):
id = models.AutoField(primary_key=True)
field1 = models.CharField(max_length=20)
field2 = models.CharField(max_length=20)
field3 = models.CharField(max_length=20)
class Meta:
unique_together = ('field1', 'field2', 'field3')外键直接关联主键
id
。优点:查询、级联、admin 都方便。
方法 2(不推荐):
B 表存三列字段对应 A 表的三列。
手动验证组合是否存在:
1
2if not A.objects.filter(field1=f1, field2=f2, field3=f3).exists():
raise ValidationError缺点:无法自动级联,admin 和 ORM 查询不方便。
外键(ForeignKey)
一对一:表示 一条记录对应另一条记录。
1
2
3class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
birthday = models.DateField()常用于扩展
User
表不想用主键来关联的情况
在 Django 中,
OneToOneField
通常用于建立一对一的关系,它默认关联到目标模型的主键。如果你需要通过非主键字段建立一对一关系,可以使用ForeignKey
并设置unique=True
。这样可以实现类似一对一的关系,但实际上是通过非主键字段进行关联。1
2
3
4
5
6
7
8
9from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, unique=True)
birthday = models.DateField()
def __str__(self):
return f"{self.user.username}'s profile"在这个例子中:
user
字段是一个ForeignKey
,关联到User
模型。unique=True
确保每个User
只能关联一个UserProfile
,从而实现一对一的关系。
为什么不能直接使用
OneToOneField
指定非主键字段?OneToOneField
是ForeignKey
的一个特例,它默认关联到目标模型的主键。Django 的OneToOneField
不支持直接指定非主键字段作为关联字段。如果你需要通过非主键字段建立一对一关系,必须使用ForeignKey
并设置unique=True
。示例:通过非主键字段建立一对一关系
假设你有一个
User
模型和一个UserProfile
模型,你希望通过User
的email
字段建立一对一关系。你可以这样实现:1
2
3
4
5
6
7
8
9from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, unique=True, to_field='email')
birthday = models.DateField()
def __str__(self):
return f"{self.user.username}'s profile"在这个例子中:
to_field='email'
指定了User
模型的email
字段作为关联字段。unique=True
确保每个User
的email
只能关联一个UserProfile
一对多关系:默认关联目标模型的 主键字段(
id
)。1
2
3
4
5
6class Author(models.Model):
name = models.CharField(max_length=50)
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey(Author, on_delete=models.CASCADE)数据库中生成
author_id
列。on_delete
常用选项:CASCADE
:父表删除,子表删除SET_NULL
:父表删除,子表字段置 NULLPROTECT
:阻止删除父表SET_DEFAULT
:设置默认值DO_NOTHING
:不做操作可用
related_name
设置反向查询:1
author = models.ForeignKey(Author, related_name="books", on_delete=models.CASCADE)
多对多(ManyToManyField):表示多条记录与多条记录的关系。
1
2
3
4
5
6class Book(models.Model):
title = models.CharField(max_length=100)
class Reader(models.Model):
name = models.CharField(max_length=50)
books = models.ManyToManyField(Book, related_name="readers")Django 会自动创建中间关联表,可通过
through
指定自定义关联表。
Django 外键实际关联原理
外键字段对应 目标模型的主键(默认
id
)。数据库中存储
字段名_id
。查询时 Django 会自动返回关联对象:
1
2book = Book.objects.get(id=1)
print(book.author.name)反向查询:
1
2author = Author.objects.get(id=1)
author.book_set.all() # 默认 related_name=modelname_set
关键点总结表
关系类型 | Django 字段类型 | 对应数据库结构 | 示例用途 |
---|---|---|---|
一对多 | ForeignKey | 表 A.id ↔ 表 B.a_id | 订单 → 用户 |
一对一 | OneToOneField | 表 A.id ↔ 表 B.a_id | 用户 → 用户详情 |
多对多 | ManyToManyField | 中间关联表 | 读者 ↔ 书 |
主键唯一标识 | AutoField/UUIDField | 表的唯一列 | 每条记录唯一 |
复合主键(推荐方式) | AutoField + unique_together | 单列主键 + 多列唯一约束 | 组合字段唯一,方便外键关联 |
Django Admin
Django 自带的 Admin 管理界面非常强大,可以方便地管理数据库中的数据。以下是一些基本配置:
注册模型
在你的应用的 admin.py
文件中,注册你的模型以便在 Admin 界面中管理。例如:
1 | # myapp/admin.py |
自定义 Admin 界面
你可以自定义 Admin 界面的显示方式。例如:
1 | # myapp/admin.py |
迁移模型
在 Django 中修改模型后,需要通过迁移(migrations)来更新数据库结构。以下是详细的步骤:
修改模型
首先,修改你的模型。例如,假设你有一个 UserProfile
模型,你想要添加一个新的字段 phone_number
:
1 | # models.py |
生成迁移文件
运行以下命令生成迁移文件:
1 | python manage.py makemigrations |
这个命令会检查你的模型定义,并生成相应的迁移文件。迁移文件会保存在应用的 migrations
文件夹中。例如:
1 | myapp/ |
查看迁移文件
打开生成的迁移文件,确认生成的内容是否符合你的预期。例如:
1 | # myapp/migrations/0002_add_phone_number.py |
应用迁移
运行以下命令应用迁移,更新数据库结构:
1 | python manage.py migrate |
这个命令会应用所有未应用的迁移文件,更新数据库结构。例如:
1 | Operations to perform: |
验证迁移
访问 Django Admin 或使用 Django Shell 验证迁移是否成功。例如:
1 | python manage.py shell |
在 Shell 中,你可以检查新字段是否已经添加:
1 | from myapp.models import UserProfile |
处理数据迁移
如果你需要在迁移过程中处理数据,可以使用 RunPython
操作。例如,假设你需要在添加新字段时初始化一些数据:
1 | # myapp/migrations/0002_add_phone_number.py |
回滚迁移
如果你需要回滚迁移,可以使用以下命令:
1 | python manage.py migrate myapp 0001 |
这个命令会将 myapp
的迁移回滚到 0001_initial
状态。
django test
常见测试类
django.test.TestCase
- 最常用,继承自
unittest.TestCase
,会自动使用测试数据库(运行前建库,结束后清理)。 - 自带断言方法(如
self.assertContains
、self.assertTemplateUsed
)。
- 最常用,继承自
django.test.SimpleTestCase
- 不需要数据库时使用(更快)。
- 适合测试一些工具函数、纯逻辑。
django.test.TransactionTestCase
- 会在数据库层执行事务测试,适合验证事务回滚逻辑。
- 比
TestCase
慢。
django.test.LiveServerTestCase
- 启动一个临时服务,结合 Selenium 等工具做端到端(E2E)测试。
安全相关
jwt
token