Django基础
Django是一个高级的Python Web开发框架,它采用了MVC(Model-View-Controller)的软件设计模式,旨在帮助开发人员快速构建高质量的Web应用程序。
Django的特点
特点 | 描述 |
---|---|
强大的ORM | 提供了一个强大的对象关系映射层,简化数据库操作 |
完整的功能集 | 内置了许多常用的功能,如身份验证、URL路由、表单处理等 |
自动化的管理界面 | 自动生成管理界面,方便管理数据库模型和数据 |
灵活的模板系统 | 支持模板继承、条件逻辑、循环和变量插值等功能 |
强调代码复用 | 通过模块化和组件化的设计,促进代码复用和可维护性 |
丰富的第三方生态系统 | 庞大的社区支持,提供了大量的插件、应用和开源项目 |
高度可扩展性 | 支持插件和第三方应用的集成,方便扩展和定制化开发 |
强调安全性 | 提供了多种安全机制和防护措施,保护Web应用的安全性 |
广泛的应用领域 | 适用于构建各种类型的Web应用程序,从小型网站到大型应用平台 |
全面的文档和支持 | 提供了全面的官方文档和教程,社区活跃,有很多资源和解决方案可用 |
本教程使用软件版本
软件名称 | 版本 |
---|---|
python | 3.11.0 |
django | 4.2.1 |
Django安装与配置
安装python虚拟环境
sudo pip install virtualenv |
加载虚拟环境并安装django
source venv3.11/bin/activate |
创建名为pydj的django项目和api的应用
django-admin startproject pydj |
项目目录结构
pydj |
调整pydj/pydj目录为pydj/config;编辑manage.py文件中main函数以下参数:
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings') |
编辑pydj/config/settings.py文件以下参数:
ROOT_URLCONF = 'config.urls' |
再次查看django目录结构
pydj |
运行django项目
python manage.py runserver |
路由
在Django中,路由(Routing)是指将URL请求映射到相应的视图函数或类视图的过程。Django使用URLconf(URL配置)来定义应用程序的路由规则。
URLconf是一个Python模块,它包含了URL模式(URL patterns)和视图函数或类视图之间的映射关系。当用户在浏览器中输入一个URL时,Django的路由系统会根据URLconf中定义的规则,找到匹配的URL模式,并将请求转发给相应的视图处理函数。
路由基本语法
from django.urls import path |
路由模式
模式 | 匹配规则 |
---|---|
path |
使用简单的字符串匹配路径,不支持正则表达式 |
re_path |
使用正则表达式匹配路径,可以捕获参数作为视图函数的参数 |
include |
引入其他应用程序的URLconf,用于实现嵌套路由 |
redirect |
重定向到其他URL |
reverse |
根据给定的视图名称或URL模式名称生成URL |
resolve |
根据给定的URL解析到相应的视图函数或类视图 |
namespace |
为应用程序指定命名空间,用于区分不同应用程序的URLconf |
案例
URL模式 | 匹配规则 |
---|---|
^articles$ |
以articles 开头,以articles 结尾,严格限制路径 |
^(?P<year>[0-9]{4})/$ |
以四位数字开头,以斜杠结尾,捕获年份作为参数 |
^post/(?P<slug>[-\w]+)/$ |
以post/ 开头,以斜杠结尾,捕获URL中的slug作为参数 |
^blog/(?P<category>[\w]+)/$ |
以blog/ 开头,以斜杠结尾,捕获URL中的category作为参数 |
^users/(?P<username>[\w]+)/profile/$ |
以users/ 开头,以/profile/ 结尾,捕获URL中的username作为参数 |
分组命名匹配
分组命名匹配是一种在正则表达式中使用括号进行分组,并为每个分组指定一个名称的技术。它允许在正则表达式匹配期间捕获和提取特定部分的值,并为每个部分分配一个有意义的名称。 通常,在正则表达式中使用括号创建分组,以便在匹配期间捕获相关的值。
示例
下面url分组命名匹配详细介绍:
URL模式 | 视图函数 | 访问示例 |
---|---|---|
r'articles/(?P<year>[0-9]{4})' |
aaa(request, year) |
/articles/2022/ |
r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$' |
bbb(request, year, month) |
/articles/2022/05/ |
r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$' |
ccc(request, year, month, day) |
/articles/2022/05/15/ |
第一行的URL模式为 articles/(?P<year>[0-9]{4})
,使用了命名参数 year
,对应的视图函数是 aaa(request, year)
。访问示例是 /articles/2022/
,其中年份为 2022
。
第二行的URL模式为 ^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$
,使用了命名参数 year
和 month
,对应的视图函数是 bbb(request, year, month)
。访问示例是 /articles/2022/05/
,其中年份为 2022
,月份为 05
。
第三行的URL模式为 ^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$
,使用了命名参数 year
、month
和 day
,对应的视图函数是 ccc(request, year, month, day)
。访问示例是 /articles/2022/05/15/
,其中年份为 2022
,月份为 05
,日期为 15
。
from django.conf.urls import url |
路由分发
在Django中,include()函数用于进行路由分发,它允许你将URL配置模块化,将不同的URL模式分发给不同的子路由模块进行处理。比如:有多个应用,app01、app02、app03;在include定义分发到对应的应用,然后在app中定义url子路由转发到对应的视图函数
示例
from django.urls import include, path |
路由命名空间
当多个应用程序或模块具有相同的URL名称时,Django会根据其所属的路由命名空间来区分它们。通过为每个应用程序或模块定义一个唯一的命名空间,可以确保URL名称的唯一性,并且可以在模板中引用正确的URL。
示例:
# myapp/urls.py |
模型
在Django中,模型(Model)是定义数据结构的Python类,用于与数据库进行交互。模型定义了数据表的结构、字段以及相关的行为,允许开发人员使用面向对象的方式来操作数据库。
Django的模型使用了对象关系映射(Object-Relational Mapping,ORM)的概念,它允许你通过操作模型对象来进行数据库的增删改查操作,而无需直接编写SQL语句。
通过定义模型,你可以创建数据库表格,并指定每个表格的字段、关联关系、验证规则等。模型类可以包含字段、方法和元数据,用于描述数据的结构和行为。
ORM的特点
优点 | 描述 |
---|---|
抽象化 | ORM屏蔽了数据库底层细节,开发人员可以使用面向对象的方式操作数据,而无需关心底层数据库操作和SQL语句的编写。 |
简化开发 | ORM提供了简洁的API和工具,加速开发过程,减少重复性工作,提高开发效率。 |
跨数据库支持 | ORM通常支持多种数据库系统,开发人员可以在不同的数据库之间切换而无需修改大量代码。 |
数据库迁移 | ORM提供了数据库迁移工具,可轻松进行数据库结构的变更和迁移,维护数据库的一致性和完整性。 |
数据一致性 | ORM通过事务管理确保数据的一致性,提供了高级的事务控制和数据完整性保护机制。 |
可移植性 | 由于ORM屏蔽了底层数据库细节,应用程序更易于迁移和部署到不同的环境和平台。 |
性能优化 | ORM框架通常提供了性能优化选项,如缓存机制、延迟加载等,可提升应用程序的响应速度和性能。 |
代码可读性 | 使用ORM可以以面向对象的方式操作数据库,使代码更易于理解和维护,提高代码的可读性和可维护性。 |
协作开发 | ORM使得多人协作开发更加容易,开发人员可以根据对象模型进行协作,而不需要处理复杂的SQL语句和数据库操作。 |
测试和调试 | ORM框架通常提供了模拟数据库环境的功能,使得单元测试和调试更加便捷,可以快速验证和修复问题。 |
模型类与ORM数据库对应关系
类 | 表 |
---|---|
类对象 | 表行 |
类属性 | 表字段 |
模型类ORM字段
ORM字段 | 描述 |
---|---|
AutoField | 自动递增的整数字段 |
BigAutoField | 自动递增的大整数字段 |
CharField | 字符串字段 |
TextField | 文本字段 |
IntegerField | 整数字段 |
BigIntegerField | 大整数字段 |
SmallIntegerField | 小整数字段 |
PositiveIntegerField | 正整数字段 |
PositiveSmallIntegerField | 正小整数字段 |
FloatField | 浮点数字段 |
DecimalField | 十进制数字段 |
BooleanField | 布尔字段 |
NullBooleanField | 可为空的布尔字段 |
DateField | 日期字段 |
DateTimeField | 日期时间字段 |
TimeField | 时间字段 |
DurationField | 时间间隔字段 |
FileField | 文件字段 |
ImageField | 图像字段 |
ForeignKey | 外键字段 |
OneToOneField | 一对一关系字段 |
ManyToManyField | 多对多关系字段 |
模型类ORM字段参数
参数 | 描述 |
---|---|
max_length | 字符串字段的最大长度 |
blank | 字段是否允许为空 |
null | 字段是否可以存储NULL值 |
default | 字段的默认值 |
primary_key | 字段是否为主键 |
unique | 字段是否唯一 |
verbose_name | 字段的可读性描述 |
help_text | 字段的帮助文本 |
choices | 字段的选项列表 |
db_index | 字段是否需要在数据库中创建索引 |
db_column | 字段在数据库中的列名 |
auto_now | 每次保存模型时,自动更新字段的值为当前时间 |
auto_now_add | 创建模型时,自动设置字段的值为当前时间 |
validators | 字段的验证器列表 |
related_name | 关联字段在关联模型中的反向引用名称 |
on_delete | 外键字段在关联对象被删除时的处理方式 |
to_field | 外键字段关联的目标模型中用于匹配的字段名称 |
related_query_name | 用于查询关联对象的名称 |
upload_to | 文件字段的上传路径 |
模型类Meta属性
模型类Meta属性主要用来设置数据库表相关属性
Meta 属性 | 描述 |
---|---|
db_table | 指定模型对应的数据库表名称 |
ordering | 模型对象的默认排序方式 |
verbose_name | 模型的可读性描述 |
verbose_name_plural | 模型的复数形式可读性描述 |
app_label | 指定模型所属的应用程序名称 |
db_alias | 指定使用的数据库别名 |
abstract | 声明模型类为抽象基类,该模型类不能被直接实例化 |
unique_together | 指定字段的组合必须是唯一的 |
indexes | 指定模型的数据库索引 |
constraints | 指定模型的数据库约束 |
default_related_name | 关联模型对象的默认反向关联名称 |
base_manager_name | 指定模型类使用的基础管理器名称 |
default_manager_name | 指定模型类使用的默认管理器名称 |
managed | 指定是否由Django自动创建数据库表格,默认为True |
get_latest_by | 指定按照某个字段的值进行最新对象查询 |
permissions | 指定模型的权限配置 |
default_permissions | 指定模型的默认权限配置 |
indexes | 指定模型的数据库索引 |
constraints | 指定模型的数据库约束 |
ORM on_delete级联模式参数
on_delete级联模式就是当删除关联表中的数据时,当前表与其关联的行为
on_delete 参数 | 描述 |
---|---|
CASCADE | 级联删除关联对象 |
PROTECT | 阻止删除关联对象 |
SET_NULL | 将关联字段设为 NULL |
SET_DEFAULT | 将关联字段设为默认值 |
SET(value) | 将关联字段设为指定的值 |
SET(…) | 将关联字段设为特定的值或调用指定的方法 |
DO_NOTHING | 什么也不做,保留关联对象而不进行任何操作 |
RESTRICT | 阻止删除关联对象(与 PROTECT 类似) |
ORM多表关系
多表关系,相当于数据库表字段的一对一、一对多、多对多
关系类型 | 描述 |
---|---|
一对一关系(One-to-One) | 每个对象只能与另一个对象建立一对一的关系 |
一对多关系(One-to-Many) | 一个对象可以关联多个对象,而多个对象只能关联到一个对象 |
多对一关系(Many-to-One) | 多个对象可以关联到一个对象,而一个对象可以关联多个对象 |
多对多关系(Many-to-Many) | 多个对象之间可以相互关联,一个对象可以关联多个对象,多个对象也可以关联到同一个对象 |
配置原生SQL
在Django settings配置文件中设置logger日志,在执行视图函数的时候可以打印完整的执行sql语句,示例:
LOGGING = { |
ORM单表操作
设计数据库表
字段名称 | 类型 | 描述 |
---|---|---|
book_name | 字符串 | 书籍名称 |
price | 浮点数 | 价格 |
publish_date | 日期 | 出版日期 |
publisher | 字符串 | 出版社 |
stock | 整数 | 库存数量 |
模型类设计
在应用models.py中定义模型类对象
from django.db import models |
模型类定义完成之后在项目config/settings.py中安装应用,应用api一般添加到INSTALLED_APPS
列表最后一个元素
INSTALLED_APPS = [ |
执行数据库迁移操作,该操作会将django模型类对象翻译为数据库sql语句并执行创建数据库表和字段及字段约束
python manage.py makemigrations |
增加数据
在视图api/views.py中定义视图函数,当访问url时,url会根据url匹配规则转发到对应视图函数并执行该视图函数完成数据库添加数据的操作
增加数据内置方法
方法 | 示例 | 描述 |
---|---|---|
save() |
models.Book(field1=value1, field2=value2, ...).save() |
保存对象到数据库。 |
create() |
models.Book.objects.create(field1=value1, ...).save() |
创建并保存对象到数据库。 |
示例:
import datetime |
查询数据
查询数据内置方法
方法 | 示例 | 描述 |
---|---|---|
all() | Model.objects.all() |
查询所有结果,结果是QuerySet 类型 |
get(**kwargs) | Model.objects.get(id=1) |
返回与给定筛选条件匹配的对象,结果返回单个对象 |
filter(**kwargs) | Model.objects.filter(name='John') |
筛选匹配对象,结果是QuerySet 类型 |
exclude(**kwargs) | Model.objects.exclude(age__lt=30) |
排除匹配条件的对象,结果是QuerySet 类型 |
order_by(field) | Model.objects.order_by('name') |
对查询结果进行排序,结果是QuerySet 类型 |
reverse() | queryset.reverse() |
对查询结果反向排序,结果是QuerySet 类型 |
count() | Model.objects.count() |
返回匹配查询对象的数量,结果是数字 |
first() | queryset.first() |
返回第一条记录对象,结果是模型对象 |
last() | queryset.last() |
返回最后一条记录对象,结果是模型对象 |
exists() | queryset.exists() |
如果QuerySet 中存在数据返回True ,否则返回False |
values(*field) | queryset.values('name', 'age') |
返回字典类型数据,包含指定字段的查询结果 |
values_list(*field) | queryset.values_list('name', 'age') |
返回元组的QuerySet 序列,包含指定字段的查询结果 |
distinct() | queryset.distinct() |
去重,去除重复的查询结果 |
案例
from django.shortcuts import HttpResponse |
过滤数据
ORM使用filter()函数用来过滤查询字段
示例
def get_books(request): |
更新数据
使用赋值方式更新数据
def update_book(request): |
使用filter过滤要更新的数据然后调用update方法更新数据
def update_book(request): |
删除数据
删除一条数据
def del_book(request): |
删除多条数据
def del_book(request): |
清除数据
def duoduiduo_clear(request): |
ORM多表操作
ORM双下划线查询内置方法
Django ORM提供了一种方便的方式来进行高级查询,即使用双下划线(__)进行字段之间的关联和过滤。这些双下划线查询可以在查询中使用多个级别的关联模型,进行字段筛选、排序和其他操作。
双下划线查询方法 | 描述 | 示例 |
---|---|---|
exact | 进行精确匹配 | Model.objects.filter(field__exact=value) |
iexact | 进行忽略大小写的精确匹配 | Model.objects.filter(field__iexact=value) |
contains | 包含指定值 | Model.objects.filter(field__contains=value) |
icontains | 包含指定值,忽略大小写 | Model.objects.filter(field__icontains=value) |
startswith | 以指定值开头 | Model.objects.filter(field__startswith=value) |
istartswith | 以指定值开头,忽略大小写 | Model.objects.filter(field__istartswith=value) |
endswith | 以指定值结尾 | Model.objects.filter(field__endswith=value) |
iendswith | 以指定值结尾,忽略大小写 | Model.objects.filter(field__iendswith=value) |
isnull | 字段是否为空 | Model.objects.filter(field__isnull=True) |
in | 匹配指定列表中的值 | Model.objects.filter(field__in=[value1, value2]) |
gt | 大于指定值 | Model.objects.filter(field__gt=value) |
gte | 大于等于指定值 | Model.objects.filter(field__gte=value) |
lt | 小于指定值 | Model.objects.filter(field__lt=value) |
lte | 小于等于指定值 | Model.objects.filter(field__lte=value) |
range | 在指定范围内 | Model.objects.filter(field__range=(value1, value2)) |
year | 获取日期字段的年份 | Model.objects.filter(date_field__year=year) |
month | 获取日期字段的月份 | Model.objects.filter(date_field__month=month) |
day | 获取日期字段的日期 | Model.objects.filter(date_field__day=day) |
一对一
表设计
将作者表中的ad字段关联到作者详情表中的id字段
| Author | AuthorDetail | |
模型类
class Author(models.Model): |
基于对象跨表查询-查询数据-正向查询
def OneByOne_get(request): |
基于对象跨表查询-查询数据-反向查询
def OneByOne_get(request): |
基于双下划线跨表查询-查询数据-正向查询
def OneByOneCheck(request): |
基于双下划线跨表查询-查询数据-反向查询
def OneByOneCheck(request): |
多对一
表设计
publish模型pub字段对应到book模型的id字段,表示一本书可以有多个出版社出版
| Publish | Book | |
模型类
class Publish(models.Model): |
基于对象跨表查询-查询数据-正向查询
def OneByMuti_get(request): |
基于对象跨表查询-查询数据-反向查询
def OneByMuti_get(request): |
基于双下划线跨表查询-查询数据-正向查询
def OneByMutiCheck(request): |
基于双下划线跨表查询-查询数据-反向查询
def OneByMutiCheck(request): |
多对多
表设计
书籍表中的pub字段和出版社id字段关联,书籍表中的作者字段和作者表中的id字段关联
| Book | Publish | |
模型类
class Book(models.Model): |
基于对象跨表查询-查询数据-正向查询
def MutiByMuti_get(request): |
基于对象跨表查询-查询数据-反向查询
def MutiByMuti_get(request): |
基于双下划线跨表查询-查询数据-正向查询
def MutiByMutiCheck(request): |
基于双下划线跨表查询-查询数据-反向查询
def MutiByMutiCheck(request): |
聚合查询
什么是聚合查询
聚合查询是数据库中的一种查询操作,用于对数据进行汇总和统计。它可以对数据集进行计数、求和、平均值、最大值、最小值等统计操作,并返回结果作为查询的输出。
聚合查询的内置方法
方法 | 描述 |
---|---|
Count() |
计算指定字段的记录数。 |
Sum() |
计算指定字段的总和。 |
Avg() |
计算指定字段的平均值。 |
Max() |
获取指定字段的最大值。 |
Min() |
获取指定字段的最小值。 |
示例
from django.db.models import Count, Sum, Avg, Max, Min |
分组查询
什么是分组查询
分组查询是一种在数据库中按照指定的字段进行分组,并对每个分组进行聚合操作的查询方式。它可以用于统计和分析数据,根据指定的条件对数据进行分类和聚合。
分组查询内置方法
方法 | 描述 |
---|---|
values() |
根据指定字段进行分组,返回每个分组的值以及聚合操作的结果。 |
annotate() |
对每个分组进行聚合操作,并将结果添加到查询结果集中。 |
order_by() |
对分组后的结果进行排序。 |
distinct() |
去除重复的分组结果。 |
aggregate() |
对每个分组进行聚合操作,并返回结果。 |
count() |
统计每个分组中的记录数。 |
Sum() |
计算每个分组中指定字段的总和。 |
Avg() |
计算每个分组中指定字段的平均值。 |
Max() |
获取每个分组中指定字段的最大值。 |
Min() |
获取每个分组中指定字段的最小值。 |
示例
from django.db.models import Count, Sum, Avg, Max, Min |
F查询
什么是F查询
F查询是Django ORM中的一种查询技术,用于在查询中引用模型字段的值,实现字段之间的比较和运算。它可以在数据库层面进行计算和过滤,避免在Python代码中进行大量的循环和条件判断。
F查询内置方法
方法 | 描述 |
---|---|
F() |
引用模型字段的值,用于字段之间的比较和运算。 |
Expression() |
创建更复杂的表达式,可以包含多个字段和运算符。 |
Q() |
组合多个表达式,用于构建复杂的查询条件。 |
F() 和Q() |
可以结合使用,实现更灵活的查询和过滤。 |
示例
from django.db.models import F, Q |
Q查询
什么Q查询
Q查询是Django ORM中的一种查询技术,用于构建复杂的查询条件。它允许使用逻辑运算符(如AND、OR、NOT)和比较运算符(如等于、大于、小于等)来组合多个查询表达式,实现更灵活的查询操作。
Q查询内置方法
方法 | 描述 |
---|---|
Q() |
创建一个查询表达式,可以使用逻辑运算符和比较运算符组合多个条件。 |
~Q() |
对查询表达式取反,用于排除满足条件的结果。 |
| (竖线) |
对查询表达式进行逻辑或(OR)操作,返回满足任一条件的结果。 |
& (和号) |
对查询表达式进行逻辑与(AND)操作,返回同时满足所有条件的结果。 |
complex_q_obj |
可以通过组合多个查询表达式来构建更复杂的查询条件。 |
示例
from django.db.models import Q |
视图
什么是Django视图
Django视图(View)是一个Python函数或类,用于处理Web应用程序中的请求和生成响应。视图负责接收用户的请求,执行必要的处理逻辑,并返回一个响应给用户。
视图在Django中起着核心的作用,它处理了应用程序的业务逻辑和用户交互,并协调模型(Model)和模板(Template)之间的交互。
视图函数(Function-based views)是最常见的视图形式,它是一个Python函数,接收一个HttpRequest对象作为参数,并返回一个HttpResponse对象作为响应。
什么是request对象
在Django中,request对象是一个包含了用户HTTP请求信息的Python对象。它是视图函数或视图类的参数之一,在处理用户请求时被传递给视图函数或方法。
request对象封装了与用户请求相关的各种信息,包括请求的URL、HTTP方法、请求头部信息、请求参数、会话信息等。通过request对象,我们可以获取和操作这些信息,以便根据用户请求的内容进行相应的处理。
request对象的属性和方法
属性/方法 | 描述 |
---|---|
request.body | 请求的原始数据,作为字节字符串 |
request.GET | 包含 GET 请求参数的字典对象 |
request.POST | 包含 POST 请求参数的字典对象 |
request.COOKIES | 包含请求中的所有 Cookie 的字典对象 |
request.FILES | 包含上传文件的字典对象 |
request.META | 包含请求的元数据(HTTP 头部信息)的字典对象 |
request.method | 获取请求的方法,例如 GET、POST |
request.path | 请求的路径部分,不包括域名和参数 |
request.path_info | 请求的路径信息,包括域名、路径和参数 |
request.get_host() | 获取请求的主机名 |
request.get_port() | 获取请求的端口号 |
request.get_full_path() | 获取完整的请求路径,包括域名、路径和参数 |
request.is_secure() | 判断请求是否使用安全连接(HTTPS) |
request.is_ajax() | 判断请求是否为 AJAX 请求 |
request.resolver_match | 匹配请求的 URL 对应的 ResolverMatch 对象 |
request.content_type | 请求的内容类型 |
request.session | 请求的会话对象 |
request.user | 当前登录用户的对象 |
request.get_full_path_info() | 获取完整的请求路径信息,包括域名、路径和参数 |
request.is_ajax() | 判断请求是否为 AJAX 请求 |
request.is_secure() | 判断请求是否使用安全连接(HTTPS) |
request.build_absolute_uri(location) | 根据给定的路径构建完整的绝对 URI |
request.get_signed_cookie(key, default=RAISE_ERROR, salt=’’, max_age=None) | 获取已签名的 Cookie |
request.set_signed_cookie(key, value, salt=’’, max_age=None, **kwargs) | 设置已签名的 Cookie |
request.get_host() | 获取请求的主机名 |
request.get_port() | 获取请求的端口号 |
request.is_secure() | 判断请求是否使用安全连接(HTTPS) |
request.get_full_path() | 获取完整的请求路径,包括域名、路径和参数 |
request.get_full_path_info() | 获取完整的请求路径信息,包括域名、路径和参数 |
request.build_absolute_uri(location) | 根据给定的路径构建完整的绝对 URI |
request.get_raw_uri() | 获取请求的原始 URI |
什么是response响应
在Web开发中,响应(Response)是服务器向客户端发送的数据,作为对客户端请求的回应。响应对象(Response Object)包含了服务器发送给客户端的内容,包括响应状态码、响应头部信息以及响应体(实际的内容)。它是客户端获取服务器返回的数据的接口。
在Django框架中,HttpResponse 是表示HTTP响应的对象。通过创建一个HttpResponse对象,你可以向客户端返回不同类型的响应,包括文本、HTML页面、JSON数据等。
response的特点
特点 | 描述 |
---|---|
表示HTTP响应的对象 | 用于向客户端发送数据作为对请求的回应 |
可设置响应的内容、状态码、头部信息和Cookie | 通过方法和属性进行设置 |
用于返回不同类型的响应 | 如文本、HTML页面、JSON数据等 |
response的方法和属性
方法/属性 | 描述 |
---|---|
HttpResponse(content, content_type=None, status=None, reason=None) |
创建一个HTTP响应对象,设置响应的内容、内容类型、状态码和状态原因 |
HttpResponse.content |
获取响应的内容 |
HttpResponse.status_code |
获取响应的状态码 |
HttpResponse.reason_phrase |
获取响应的状态原因 |
HttpResponse.charset |
获取响应的字符集 |
HttpResponse.set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=False, httponly=False, samesite=None) |
设置响应的Cookie |
HttpResponse.delete_cookie(key, path='/', domain=None) |
删除响应中的指定Cookie |
HttpResponse.get(key, default=None) |
获取响应头部信息中指定键的值 |
HttpResponse.set_header(key, value) |
设置响应头部信息中的键值对 |
案例:返回html页面
from django.http import HttpResponse |
函数视图处理get请求
from django.shortcuts import render,HttpResponse |
类视图处理get请求
from django.shortcuts import render,HttpResponse |
函数视图装饰器
def wrapper(func): |
类视图装饰器
def wrapper(func): |
Cookie
什么是Cookie
Django cookie是在Django框架中使用的一种HTTP Cookie。HTTP Cookie是由Web服务器发送到Web浏览器的小型数据片段,用于在客户端存储和检索信息。Cookie通常用于跟踪用户会话、存储用户偏好设置、记录用户行为等。
在Django中,使用cookie模块来处理和操作Cookie。Django的cookie模块提供了一些便捷的方法和函数,使得操作Cookie变得简单。通过使用Django的HttpResponse对象的set_cookie()方法,可以设置Cookie的值、过期时间、域名、路径等属性。
Cookie的特点
以下是cookie的一些特点:
特点 | 描述 |
---|---|
存储位置 | Cookie保存在客户端的浏览器中,作为浏览器的一部分。 |
数据大小 | Cookie的存储容量通常受到浏览器的限制,一般为几KB到几十KB。 |
数据传输 | Cookie会在每次HTTP请求中自动发送到服务器,包括请求头中的Cookie字段。 |
过期时间 | 可以设置Cookie的过期时间,可以是会话级别的(关闭浏览器即失效)或具体的日期和时间。 |
安全性 | Cookie是存储在客户端的,可以被用户修改和删除,因此不适合存储敏感信息。 |
跨域访问 | Cookie默认只在设置它的域名和路径下有效,不支持跨域访问。 |
持久性 | 可以设置Cookie的持久性,使其在浏览器关闭后仍然有效。 |
作用范围 | Cookie可以在整个网站的不同页面之间共享。 |
功能 | Cookie通常用于会话管理、用户认证、记住用户偏好设置等。 |
Cookie的应用场景
应用场景 | 描述 |
---|---|
会话管理 | 用于跟踪用户的会话状态,例如记录用户登录信息、验证用户身份等。 |
记住用户偏好设置 | 通过Cookie可以存储用户的偏好设置,例如语言偏好、主题选择、字体大小等。 |
购物车功能 | 通过Cookie可以在用户浏览网站时存储用户选择的商品信息,以实现购物车功能。 |
广告跟踪 | 用于追踪用户的浏览行为和兴趣,以提供个性化的广告推荐。 |
记住用户登录状态 | 通过设置一个持久性的Cookie,可以实现记住用户登录状态,避免用户每次访问都需要重新登录。 |
多域名共享数据 | 可以在多个域名之间共享数据,例如实现单点登录(SSO)功能。 |
防止恶意请求 | 可以使用Cookie来防止恶意请求,例如通过设置CSRF令牌(跨站请求伪造)来验证请求的合法性。 |
Cookie的内置方法
HttpRequest的Cookie相关属性和方法:
属性/方法 | 描述 |
---|---|
request.COOKIES | 包含请求中的所有Cookie的字典对象 |
request.COOKIES.get(key, default=None) | 获取指定Cookie的值,如果不存在则返回默认值 |
HttpResponse的Cookie相关属性和方法:
属性/方法 | 描述 |
---|---|
response.set_cookie(key, value=’’, max_age=None, expires=None, path=’/‘, domain=None, secure=False, httponly=False, samesite=None) | 设置Cookie,将Cookie添加到响应对象中 |
response.delete_cookie(key, path=’/‘, domain=None) | 删除指定的Cookie |
示例:用户登录成功之后返回给客户端一个cookie
from django.http import HttpResponse |
Session
什么是Session
Django的Session是一种在服务器端存储用户数据的机制。它基于Cookie或其他方式实现了跟踪和存储用户会话的功能。
在Django中,Session可以用来存储和检索与特定用户关联的数据,例如用户认证信息、用户偏好设置、购物车内容等。Session数据存储在服务器端,而客户端(通常是浏览器)只会在Cookie中保存一个用于标识会话的标识符。
Session的功能和特点
特点 | 功能 |
---|---|
数据存储在服务器端 | 将用户数据存储在服务器端的持久化存储中,确保数据的安全性和可控性。 |
客户端标识符 | 为每个客户端分配一个唯一的标识符(session ID),通常以Cookie形式存储在客户端,用于标识和匹配会话。 |
客户端无法篡改 | 客户端只保存会话标识符,无法直接修改会话数据,只能通过与服务器的交互来操作数据。 |
可扩展性和配置性 | 提供灵活的配置选项,如存储后端选择、过期时间设置、加密和签名等,可以根据需求进行自定义设置。 |
多种存储方式 | 可以选择不同的存储后端,如数据库、缓存等,根据应用程序的需求和规模进行选择。 |
跨请求保持状态 | 通过会话数据,可以在不同的请求之间共享和保持状态,实现用户认证、权限管理、购物车等功能。 |
灵活的数据访问 | 提供方便的API和方法,可以轻松地存储、读取和修改会话数据。 |
会话管理和过期处理 | 可以设置会话的过期时间,并提供过期处理机制,如自动清理过期会话数据。 |
与用户认证集成 | 可以与Django的用户认证系统集成,实现用户登录和身份验证功能。 |
Session的使用场景
使用场景 | 描述 |
---|---|
用户认证和身份管理 | Session可以用于存储和验证用户的身份信息,实现用户认证和登录功能。 |
用户个性化设置 | 可以使用Session存储用户的个性化设置,如主题选择、语言偏好、布局偏好等。 |
购物车功能 | 在电子商务应用中,可以使用Session来存储和管理用户的购物车信息。 |
记住登录状态 | 使用Session可以实现”记住我”的功能,让用户在下次访问时保持登录状态。 |
权限管理 | 可以使用Session来存储用户的权限信息,根据权限来控制用户对特定资源的访问。 |
表单数据暂存 | 在多步骤的表单流程中,可以使用Session暂存用户填写的表单数据,以便在下一步继续使用。 |
会话跟踪和分析 | Session可以用于跟踪用户的会话信息,记录用户的访问记录和行为分析。 |
应用状态管理 | 可以使用Session来存储应用程序的状态信息,如在线用户数、系统配置等。 |
多设备同步 | 使用Session可以实现用户在多个设备上的会话同步,保持一致的登录状态和数据状态。 |
示例:当用户登录成功后,可以使用Session来记录用户的登录状态并在后续请求中进行验证
在Django中,request对象是每个视图函数的参数,用于接收客户端发送的请求数据。对于同一个用户的请求,request对象在整个请求-响应周期内是保持不变的,因此可以在不同的视图函数之间传递数据。
在上述示例中,request对象可以在login函数和dashboard函数之间传递数据。在login函数中,当用户登录成功后,将用户名存入Session中:request.session[‘username’] = username。然后在dashboard函数中,可以通过request.session[‘username’]来获取之前存入Session的用户名。
这样,登录成功后,username信息就可以在不同的视图函数中传递和使用。但是需要注意的是,Session数据是存储在服务器端的,因此在不同的请求之间共享数据时,需要确保使用相同的Session对象(例如,使用相同的Session中间件)来访问Session数据。
from django.shortcuts import render, redirect |
Cookie和Session的区别
Cookie和Session都是用于在Web应用中跟踪和管理用户状态的机制,但在具体的使用场景和实现方式上有一些区别。
Cookie是在客户端存储的小型文本文件,用于在不同的HTTP请求之间传递数据,通常用于实现用户身份验证、记住登录状态等功能。
Session是一种服务器端的机制,用于存储和管理用户会话数据,可以在不同的请求之间保持状态,并且提供了更高的数据安全性和灵活性。在实际应用中,根据需求和安全性要求,可以选择使用Cookie、Session或两者结合来管理用户状态和传递数据。
特点 | Cookie | Session |
---|---|---|
数据存储位置 | 客户端 | 服务器端 |
存储容量 | 通常4KB左右 | 通常无明确限制,但受服务器配置和资源影响 |
生命周期 | 可设置过期时间,可以是临时的或长期的 | 通常与用户会话相关,关闭浏览器后自动删除 |
数据安全性 | 数据在客户端存储,可以被修改或窃取 | 数据存储在服务器端,相对较安全 |
存储内容 | 可以存储任意字符串数据 | 可以存储任意数据类型,包括对象、列表等 |
访问方式 | 可以通过浏览器开发工具查看和修改 | 只能通过服务器端进行访问和操作 |
中间件
什么是Django中间件
在 Django 中,中间件是一种插入到请求/响应处理过程中的组件,它可以在处理请求之前和之后执行一些操作。中间件提供了一种方便的方式来修改 Django 的请求和响应对象,以及在处理请求的各个阶段执行额外的逻辑。
中间件使用场景
使用场景 | 描述 |
---|---|
认证和授权 | 中间件可以用于验证用户的身份,检查用户是否具有足够的权限来访问特定的视图或资源。 |
请求/响应处理 | 中间件可以在请求到达视图之前或响应发送给客户端之前,对请求和响应进行处理。例如,可以对请求进行预处理,如解析请求参数、检查 CSRF 令牌等。对于响应,可以进行后处理,如添加额外的响应头、压缩响应内容等。 |
缓存和性能优化 | 中间件可以用于缓存请求的响应,以减少数据库或其他资源的访问次数,提高性能。 |
异常处理 | 中间件可以捕获视图中发生的异常,并根据需要执行适当的操作,如记录错误、发送通知等。 |
日志记录 | 中间件可以用于记录请求的详细信息,如请求的路径、处理时间等,以便后续分析和排查问题。 |
请求/响应转换 | 中间件可以修改请求或响应的内容,例如对请求进行重定向、对响应进行内容转换等。 |
Django中间件的作用
用来对请求和响应做一些统一加工和处理的,比如对所有请求中的post请求做一个csrf token认证,使用了django.middleware.csrf.CsrfViewMiddleware中间件,后面视图中能够使用request.session做一个session操作,这个request.session的功能就是在这个中间件django.contrib.sessions.middleware.SessionMiddleware中加工好的。
Django请求生命周期
1.浏览器访问/index/路径,将用户的http请求发送给wsgi封装的socket
2.wsgi将用户http请求发送给中间件,按顺序执行每个中间件的process_request方法
3.中间件执行完成之后交给url控制器,将用户访问url路径解析成相应视图函数
4.视图函数通过数据库模型、template模板渲染,将数据返回给中间件
5.中间件按倒序执行每个中间件的response方法
6.中间件将数据返回给wsgi,由wsgi按http协议封装成响应的数据返回给浏览器
自定义中间件
自定义中间件的流程:
1.在app文件夹下创建一个文件夹,比如:custommiddleware
2.在custommiddleware文件夹下创建py文件,比如:middlewares
3.在middlewares.py文件中写如下内容
#只有response_request方法函数返回None表示该函数的流程是正常的。 |
在settings.py配置文件中引入中间件
MIDDLEWARE = [ |
中间件常用的五个方法
方法 | 描述 |
---|---|
process_request(self, request) |
在每个请求到达中间件时调用,对请求进行预处理。 |
process_view(self, request, view_func, view_args, view_kwargs) |
在视图函数被调用之前调用,可以对视图进行处理。 |
process_exception(self, request, exception) |
在视图函数抛出异常时调用,可以捕获并处理异常。 |
process_response(self, request, response) |
在响应发送给客户端之前调用,对响应进行后处理。 |
process_template_response(self, request, response) |
在响应是模板响应对象时调用,对模板响应进行处理。 |
process_request中间件方法
1.如果有两个中间件,其中一个中间件process_request返回的是None,那么才会继续执行后面的中间件的process_request方法;
2.如果最后一个中间件返回None,那么逻辑才会继续执行到url路由控制器;
3.如果process_request里面return的是一个HttpResponse对象,那么后面的中间件的process_request将不再执行,也不会走到url控制器。
process_response中间件方法
注意:
1.自定义的中间件如果定义了process_response中间件方法,必须要return response
2.如果有两个中间件md1、md2,如果md1中间件process_request返回的是HttpResponse,那么中间件md2的process_request和process_response方法都不会执行,直接把md1的process_response返回。
def process_response(self,request,response): |
process_views中间件方法
process_views执行顺序:
1.当一个请求到达 Django 时,它会经过 process_request 方法的处理,然后进入 URL 路由系统,确定要调用的视图函数。在调用视图函数之前,会依次执行每个中间件的 process_view 方法。
2.如果在中间件的 process_view 方法中返回了一个响应对象,那么后续的中间件的 process_view 方法以及视图函数本身将不会被执行,请求将直接返回该响应对象。
3.如果所有中间件的 process_view 方法都执行完毕,且没有返回响应对象,那么 Django 将继续调用确定的视图函数来处理请求。在视图函数执行完毕后,会按照相反的顺序依次执行中间件的 process_response 方法。
使用案例:
def process_view(self,request,view_func,view_args,view_kwargs): |
process_exception中间件方法
执行顺序:
1.当一个视图函数抛出异常时,Django 会依次调用每个中间件的 process_exception 方法,直到其中一个中间件处理了该异常并返回一个响应对象,或者所有中间件的 process_exception 方法都执行完毕。
2.如果一个中间件的 process_exception 方法返回了一个响应对象,那么后续的中间件的 process_exception 方法将不会被执行,请求将直接返回该响应对象。
3.如果所有中间件的 process_exception 方法都执行完毕且没有返回响应对象,Django 将继续处理该异常,默认行为是将异常传递给 Django 的异常处理机制。
def process_exception(self,request,exception): |
process_template_response中间件方
执行顺序:
1.当一个视图函数返回一个模板响应对象时,Django 会依次调用每个中间件的 process_template_response 方法。
2.在 process_template_response 方法中,中间件可以对模板响应进行处理,例如添加模板变量、修改模板上下文等。
3.如果一个中间件的 process_template_response 方法返回了一个响应对象,那么后续的中间件的 process_template_response 方法将不会被执行,请求将直接返回该响应对象。
4.如果所有中间件的 process_template_response 方法都执行完毕且没有返回响应对象,Django 将继续发送模板响应给客户端。
def process_template_response(self,request,response): |
用户认证和授权
什么是用户的认证和授权
- 用户认证指的是验证用户的身份,确保用户是合法的、已注册的用户。Django 提供了内置的身份验证系统,它可以处理用户的注册、登录、注销等功能。通过用户认证,应用程序可以验证用户提供的凭据(如用户名和密码),并识别用户身份。
- 用户授权是指确定用户是否具有足够的权限来执行特定的操作或访问特定的资源。Django 提供了基于角色和权限的授权系统。在授权系统中,可以定义用户角色和分配相应的权限,然后根据用户的角色和权限,决定其是否具有执行某个操作或访问某个资源的权限。
用户认证和授权的功能
功能 | 描述 |
---|---|
用户模型 (User Model) | 内置的用户模型,用于存储用户的身份信息,如用户名、密码等。可以通过扩展用户模型来添加自定义的用户属性。 |
身份验证后端 (Authentication Backends) | 处理用户的认证过程,包括验证用户凭据、检查用户状态等。可以选择合适的身份验证后端来满足应用程序的需求。 |
登录视图 (Login View) | 内置的登录视图,显示登录表单、验证用户凭据并进行身份验证。可自定义登录视图以适应应用程序的需求。 |
注销视图 (Logout View) | 内置的注销视图,用于注销当前用户并清除用户的会话信息。 |
装饰器和权限验证 (Decorators and Permissions) | 通过装饰器和权限验证限制对某些视图或资源的访问。只有具有适当权限的用户才能执行相应的操作。 |
用户组和权限 (User Groups and Permissions) | 管理用户组和权限,用户组是一组用户的集合,可以为用户组分配权限。通过分配用户到用户组,可以方便地管理用户的权限。 |
实现认证授权的步骤
- 定义用户模型:使用 Django 的内置用户模型 (
django.contrib.auth.models.User
) 或扩展它来定义自定义用户模型。用户模型用于存储用户的身份信息。 - 配置认证后端:在 Django 的配置文件 (
settings.py
) 中配置认证后端 (AUTHENTICATION_BACKENDS
),选择适合你应用程序需求的后端。例如,使用 Django 的内置后端 (django.contrib.auth.backends.ModelBackend
) 来验证用户的凭据。 - 创建登录视图:定义登录视图,用于显示登录表单并处理用户提交的登录凭据。你可以使用 Django 的内置登录视图 (
django.contrib.auth.views.LoginView
) 或自定义视图来处理登录逻辑。 - 创建注销视图:定义注销视图,用于注销当前用户并清除用户的会话信息。你可以使用 Django 的内置注销视图 (
django.contrib.auth.views.LogoutView
) 或自定义视图来处理注销逻辑。 - 保护视图和资源:通过装饰器或权限验证来限制对某些视图或资源的访问。使用
@login_required
装饰器来要求用户登录才能访问某个视图。使用@permission_required
装饰器来要求用户具有特定权限才能访问某个视图。 - 定义用户组和权限:使用 Django 的用户组和权限管理功能来组织用户并分配权限。可以创建用户组,将用户添加到组中,并为组分配适当的权限。通过授权用户组,可以更方便地管理用户的权限。
- 使用 Django 表单和模板标签:Django 提供了与用户认证和授权相关的表单和模板标签,如登录表单 (
AuthenticationForm
)、用户信息表单 (UserCreationForm
、UserChangeForm
)、用户认证模板标签 ({% if user.is_authenticated %}
) 等。可以使用这些工具来简化用户认证和授权的开发。
示例
普通用户:文章增删改查权限
管理员用户:文章、用户增删改查权限
1.定义用户模型:
from django.contrib.auth.models import AbstractUser |
2.创建文章模型:
from django.db import models |
3.创建视图和表单:
from django.shortcuts import render, get_object_or_404, redirect |
4.配置 URL 路由:
from django.urls import path |
5.创建文章表单:
from django import forms |
6.定义权限:
在 Django 的权限系统中,为普通用户和管理员用户分配相应的权限。
- 普通用户权限:
your_app.view_article
: 查看文章your_app.add_article
: 添加文章your_app.change_article
: 修改文章your_app.delete_article
: 删除文章
- 管理员用户权限:
your_app.view_article
: 查看文章your_app.add_article
: 添加文章