1. Django项目创建
1.1. Pycharm创建Django项目
1.1.1. manage.py
是Django用于管理本项目的命令行工具,之后进行站点运行,数据库自动生成等都是通过本文件完成。
"""Django's command-line utility for administrative tasks."""
import os
import sys
def main():
"""Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'DjangoProjectBossZp.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()
1.1.2. _init_.py
告诉Python该目录是一个Python包,暂无内容,后期一些工具的初始化可能会用到。
1.1.3. asgi.py
定义ASGI的接口信息,和WSGI类似,在3.0版本之后新增ASGI,相比WSGI,ASGI实现了异步处理,用启动异步通信服务,比如:实现在线聊天等异步通信功能。(类似Tornado异步框架)
1.1.4. settings.py
Django项目的配置文件,默认状态其中定义了本项目引用的组件,项目名,数据库,静态资源等。
内容详情介绍
1.1.4.1. 项目根目录
#找到当前文件的父目录的父目录
BASE_DIR = Path(__file__).resolve().parent.parent
1.1.4.2. 项目的秘钥
SECRET_KEY = 'django-insecure-@4t==xj$d8!s5s*2f$!&zhb7p3f0ovdg=????)*hbe9@j)$%kr'
1.1.4.3. 是否使用调试模式
True:表示调试模式,一般用于开发过程中
False:表示非调试模式,一般用于上线部署
DEBUG = True
1.1.4.4. 被允许的域名/IP
*:表示通配符,匹配所有IP
ALLOWED_HOSTS = ['*']
1.1.4.5. 定义应用
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# 定义自己的应用
'myApp',
]
1.1.4.6. 中间件
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
1.1.4.7. 根路由
ROOT_URLCONF = 'DjangoProject.urls'
1.1.4.8. 模版
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates']
,
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
1.1.4.9. 数据库
# 配置数据库信息
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', #存储引擎
'NAME': 'Test', #数据层名称
'USER': 'root', #用户名
'PASSWORD': '5111111', #密码
'HOST': 'localhost', #数据库地址
'PORT': '3306' #端口号
}
}
1.1.4.10. 国际化
LANGUAGE_CODE = 'zh-hans' #en-us 英文, zh-hans中文
TIME_ZONE = 'Asia/Shanghai' #时区
USE_I18N = True
USE_TZ = True
1.1.4.11. 静态文件static(CSS,JavaScript,Images)
STATIC_URL = 'static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR,'static'),
)
1.1.4.12. 默认的主键字段类型
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
1.1.5. urls.py
维护项目的URL路由映射,即定义当前客户端访问时由哪个模块进行响应。
1.1.6. wsgi.py
全程为Python Web Server Gateway Interface,即Python服务器网关接口,是Python应用与Web服务器之间接口,用于Django项目在服务器上的部署和上线,一般不需要修改。
1.2. 测试服务器的启动
可以直接进行服务运行,默认执行起来的端口是8000。也可以自己指定IP和端口:
监听机器所有可用IP(电脑可能有多个内网IP或多个外网IP):
python manage.py runserver 0.0.0.0:8000
同时在settings.py中将ALLOWED_HOSTS=['*'],在其他局域网电脑上可以通过在浏览器输入Django项目所在的电脑的IP:8000来访问
1.3. 数据迁移
1.3.1. 创建数据库迁移文件
Django 中的迁移(migrations)是一种记录数据库模型更改的方法。当你在 Django 项目中修改了模型(如添加、删除或修改字段),你需要运行 makemigrations 命令来生成迁移文件,它会将这些模型更改的信息记录下来。
迁移文件实际上是一个包含了一系列数据库操作命令的 Python 脚本,它描述了如何使数据库与当前模型保持同步。通过运行 makemigrations 命令,Django 会自动检测你对模型的更改,并生成相应的迁移文件。
一旦生成了迁移文件,你可以使用 python manage.py migrate 命令来应用这些迁移,将数据库更新为最新的模型状态。
当你运行这个命令时,Django 会提示你输入用户名、电子邮件地址以及密码等信息来创建超级用户。一旦创建成功,你就可以使用这个超级用户账号来登录后台管理界面,管理网站的内容和用户。
python manage.py makemigrations
1.3.2. 将数据库迁移到最新模型状态
当你运行 makemigrations 命令生成了迁移文件后,你可以使用 migrate 命令来应用这些迁移,将数据库结构更新为最新的模型状态。这个命令会执行迁移文件中描述的数据库操作命令,例如创建表、修改字段等。
通常情况下,你需要先运行 makemigrations 命令生成迁移文件,然后再运行 migrate 命令将这些迁移应用到数据库中。这样可以保持数据库和模型的一致性。
python manage.py migrate
注意:不需要初始化迁移文件夹,每个应用默认有迁移文件migrations
1.4. 创建应用
python manage.py startapp myApp # myApp为Application的名称,可随意
使用应用前需要将应用配置到项目中,在settings中将应用加入到INSTALLED_APPS选项中
- 应用目录介绍
- __init__.py 其中暂无内容,使得app成为一个包
- admin.py 管理站点模型的声明文件,默认为空
- apps.py 应用信息定义文件,在其中生成了AppConfig,该类用于定义应用名等
- models.py 添加模型层数据类文件
- views.py 定义URL相应函数,视图函数
- migrantions包 自动生成,生成迁移文件的
- test.py 测试代码文件
1.5. 基本视图
在浏览器中访问地址时,我们的路由会先做匹配,会匹配浏览器端口后面的字符串,在项目中默认会去找根路由,在根路由中找到字符串,然后再去访问对应的视图函数,然后返回响应。
1.6. 路由
1.6.1. 主配置文件下面为项目的主路由
urlpatterns = [
path('admin/', admin.site.urls),
path('myApp/', include('myApp.urls'))
]
1.6.2. 自己创建的应用程序下面可以新建urls.py为子路由
一个应用对应一个路由
# 子路由格式 path('',views.home, name='home')
urlpatterns = [
path('home/',views.home,name='home'),
path('login/', views.login, name='login'),
path('registry/', views.registry, name='registry'),
]
1.7. 模版templates
创建模版文件夹templates,在模版文件夹中创建模版文件
在views中去加载渲染模版,使用render函数:
return render(request,'index.html')
1.8. 数据库模型
Model模型 <===> 表
类结构 <===> 表结构
类属性 <===> 表字段
对象 <===> 表的一行记录
在models.py中引入Models,创建自己的模型,切记要继承自models.Model
from django.db import models
class User(models.Model):
#对应的SQL:id,主键
id = models.AutoField('id',primary_key=True)
class Meta:
db_table = "user"
1.9. Admin后台管理系统
在Admin.py中将model加入后台管理:admin.site.register(Grade)
创建超级管理用户,访问Admin后台:http://127.0.0.1:8000/admin/
在 Django 项目中,超级用户是具有最高权限的用户,可以访问后台管理界面并具有管理整个网站的权限。通过运行 createsuperuser 命令,你可以在数据库中创建一个新的超级用户账号。
当你运行这个命令时,Django 会提示你输入用户名、电子邮件地址以及密码等信息来创建超级用户。一旦创建成功,你就可以使用这个超级用户账号来登录后台管理界面,管理网站的内容和用户。
python manage.py createsuperuser
2. Django路由Router
2.1. 路由Router
在实际开发工程中,一个Django项目会包含很多的App,这时候如果我们只在主路由里,进行配置就会显得杂乱无章,所以通常会在每个App里,创建各自的urls.py路由模块,然后从根路由出发,将app所属的url请求,全部转发到相应的urls.py模块。而这个从主路由转发到各个应用路由的过程叫做路由的分发
2.2. 命名空间
在实际应用中,Django中可能存在多个应用程序,每个应用程序都可能有自己的路由模块。为了防止路由冲突,Django提供了命名空间(namespace)的概念。命名空间是一种将路由命名为层次结构的方式,使得在查询路由时,可以限定在该命名空间内。
path('app/', include(('App.urls', "App"),namesoace='App'))
2.3. 反向解析
Django路由反向解析是一个非常重要的功能,他可以让我们在代码中使用路由别名替代URL路径,在修改URL时,避免代码中的硬编码依赖,同时也可以提高可读性和可维护性。
2.4. 重定向
通过各种方法将各种网络请求重新定个方向转到其他位置
Django中的重定向:当视图函数处理完一个逻辑后,不需要向客户端呈现数据,而是转回到其他页面(可以理解为调用其他的视图函数)通俗解释为:视图转向视图,而不是直接返回到模版html
重定向的使用:如添加成功,修改成功,删除成功后显示数据列表,而数据的列表已经开发完成,此时不需要重新编写获取列表的代码,而是转到这个视图。
Django中提供了HttpResponseRedirect对象实现重定向功能,这个类继承自HttpResponse,别定义在Django.html模块中。
3. Django模版
3.1. 模版Template
在Django框架中,莫办事可以帮助开发者快速生成呈现给用户页面的工具
模版的设计方式实现了我们MVT中VT解耦(M:Model,V:View,T:Template),VT有着N:M的关系,一个V可以调用任意T,一个T可以供给任意V使用
模版中的动态代码段,除了做基本的静态填充,还可以实现一些基本的运算,转换和逻辑
3.1.1. 变量
视图传递给模版的数据,遵守标识符规则
{{ var }} #如果变量不存在,则插入空字符串
3.1.2. 方法不能有参数
{{ str.upper }} #不能有括号
3.1.3. 列表
{{ item.2 }}
3.1.4. 标签
作用
- 加载外部传入的变量
- 在输出中创建文本
- 控制循环或逻辑
{% tag %}
3.1.5. if语句语法
if 语句:
格式:
if单分支
{% if 表达式 %}
语句
{% endif %}
if双分支
{% if 表达式 %}
语句
{% else %}
语句
{% endif %}
if多分支
{% if 表达式 %}
语句
{% elif %}
语句
{% else %}
语句
{% endif %}
3.1.6. 判断true或false语法
{% if today_is_weekend %}
<p>Welcome to the weekend!</p>
{% endif %}
3.1.7. 使用 and or not
{% if athlete_list and coach_list %}
<p>Both athlete and coaches are available.</p>
{% endif %}
{% if not athlete_list %}
<p>There are no athletes.</p>
{% endif %}
3.1.8. 继承
# extend继承,写在开头位置
{% extend '父模版路径' %}
include:加载模版进行渲染
{% include '模版文件' %}
{{ block.super }} :获取父模版中的block中的内容
4. Jinja2
Jinja2是Flask框架中的一个模版引擎,是模仿Django默认模版引擎基础上开发的,比Django模版引擎性能更好,功能更全。
Jinja2宣称比Django默认模版引擎快10-20倍,Django也支持Jinja2
4.1. 安装Jinja2模块
pip install jinja2
4.2. 在settings.py所在的目录中创建jinja2_env.py文件,并写入以下内容
from diango.templatetags.static import static
from django.urls import reverse
from jinja import Environment
def environment(**options):
env = Environmrnt(**options)
env.globals.update({
'static':static,
'url':reverse,
})
return env
4.3. 在settings.py文件中配置jinja2模版引擎
TEMPLATES = [
{
# 添加jinja2模版
'BACKEND': 'django.template.backends.jinja2.Jinja2',
'DIRS': [BASE_DIR / 'templates'],
'APP_DIRS': True,
'OPTIONS': {
# 这里添加environment,并指定到jinja2_env文件中的environment
'environment':'DjangoProjectBossZp.jinja2_env.environmrnt'
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
5. Django模型
5.1. models字段类型
5.1.1. 概述
Django根据属性的类型确定以下信息
- 当前选择的数据库支持字段的类型
- 渲染管理表单时使用的默认html空间
- 在管理站点最低限度的验证
Django会为表增加自动增长的主键列,每个模型只能有一个主键列,如果使用选项设置某属性为主键列后,则Django不会再生成默认的主键列
5.1.2. 属性命名限制
- 遵循标识符规则
- 由于Django的查询方式,不允许使用连续的下划线
定义属性时,需要字段类型,字段类型被定义在django.db.models.fields目录下,为了方便使用,被导入到django.db.models中
5.1.3. 使用方式
- 导入from django.db import models
- 通过models.Field创建字段类型的对象,赋值给属性
逻辑删除和物理删除
对于重要数据都做逻辑删除,不做物理删除,实现方法是定义is_delete属性,类型为BooleanField,默认值为False
is_delete = models.BooleanField(default=False)
5.1.4. 常用字段类型
- AutoField
-
- 一个根据实际ID自动增长的IntegerField,通常不指定,如果不指定,主键字段id将自动增加到模型中
- CharField(max_length=字符长度)
字符串,默认表单样式是Input
- TextField
大文本字段,一般超过4000使用,默认表单空间是Textarea
- IntegerField 整数
- DecimalField(max_digits=None, decimal_places=None)
-
- 使用python的decimal实例表示的十进制浮点数
- 参数说明
-
-
- DecimalField.max_digits 位数总数(最大长度)
- DecimalField.decimal_places 小数点后的数字位数
-
- FloatField
用Python的float实例来表示的浮点数
- BooleanField
True/False字段,此字段的默认表单控制是CheckboxInput
- DateField([auto_now=False,auto_now_add=False])
使用Python的datetime.date实例表示的日期
参数说明
DateField.auto_now
每次保存对象时,自动设置该字段为当前时间,用于“最后一次修改”的时间戳,它总是使用当前日期,默认为false
注意:auto_now_add,auto_now,add default 这些设置时相互排斥的,他们之间的任何组合将会发生错误的结果
- TimeField
使用Python的datetime.time实例表示的时间,参数同DateField
- DateTimeField
使用Python的datetime.datetime实例表示的日期和时间,参数同DateField
- FileField
一个上传文件的字段
- ImageField
继承了FileField的所有属性和方法,但对上传的对象进行校验,确保它是个有效的image
需要安装Pillow:pip install Pillow
5.2. 常用字段参数
- null=True 数据库中字段是否可以为空
- blank=True Django的Admin中添加数据时是否可允许空值
一般null=True&blank=True搭配使用,出现null=True就用上blank=True
- primary_key = True
主键,对AutoField设置主键后,就会代替原来的自增ID列
- auto_now 和 auto_now_add
auto_now 自动创建---无论添加或修改,都是当前操作的时间
auto_now_add 自动创建---永远是创建的时间
- choices (后台Admin下拉菜单)
USER_TYPE_LIST = (
(1,'超级用户'),
(2,'普通用户')
)
user_type = models.InterField(choices=USER_TYOE_LIST,
default=1,verbose_name='用户类型')
- max_length 最大长度
- default 默认值
- verbose_name Admin(后台显示的名称)中字段的显示名称
- name | db_column 数据库中的字段名称
- unique = True 不允许重复
- db_index = True 数据库索引,例如:如果你想通过name查询更快的话,给他设置为索引即可
- editable = True 在Admin里是否可编辑,不可编辑则不显示
- 设置表名
class Meta:
db_table = 'person'
5.3. models基本操作
一般的数据库操作流程:
- 创建数据库,设计表结构和字段
- 链接MySQL数据库,并编写数据访问层代码
- 业务逻辑层去调用数据访问层执行数据库操作
Django通过Model操作数据库,不管数据库的类型是MySQL或者Sqlite,Django自动帮你生成相对应数据库类型的SQL语句,所以不需要关注SQL语句和类型,对数据的操作,Django帮我们自动完成。只会写Model就可以了。
Django使用对象关系映射(Object Relational Mapping,简称ORM)框架去操控数据库。
ORM(Object Relational Mapping)对象关系映射,是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。
5.3.1. 增
创建对象实例,然后调用save方法
obj = Author()
obj.first_name = ' '
obj.first_name = ' '
obj.save()
创建对象并初始化,再调用save方法
obj = Author(first_name = '',first_name = '')
obj.save()
使用create方法
Author.objects.create(first_name = '', first_name = '')
使用get_or_create方法,可以防止重复
Author.object.get_or_create(first_name = '', first_name = '')
5.3.2. 删
使用Queryset的delete方法
删除指定条件的数据
Auto.objects.filter(first_name = '').delete()
删除所有数据
Author.objects.all().delete()
注意:objects不能直接调用delete方法
使用模型对象的delete方法
obj = Author.objcts.get(id = 2)
obj.delete()
5.3.3. 改
Author.objects.filter(last_name='').update(last_name='')
模型没有定义update方法,直接给字段赋值,并调用save,能实现update的功能,例如:
obj = Author.objects.get(id = 3)
obj.first_name = ''
obj.save()
save更新时会更新所有字段。如果只想更新某个字段,减少数据库操作,可以这样做:
obj.first_name = ''
obj.save(update_fields=['first_name'])
5.3.4. 查
get(): 获取单条数据:
Author.objects.get(id= 1)
如果没有找到符合条件的对象,会引发模型类.DoesNotExist 异常
如果找到多个,会引发模型.MultipleObjectsReturned 异常
first():返回查询集(QuerySet)中的第一个对象
last():返回查询集中的最后一个对象
count():返回当前查询集中的对象个数
all():获取全部数据:
Author.object.all()
values():获取指定列的值,可以传多个参数,返回包含字典的列表(保存了字段名和对应的值)
Author.objects.all().values('')
values_list():获取指定列的值,可以传多个参数,返回包含元组列表(只保存值)
Author.objects.all().values_list('')
进阶操作
获取个数
Author.objects.filter(name='seven').count()
Author.objects.filter(id_gt=1) #获取id大于1的值
#selete * from Author where id > 1
Author.objects.filter(id_gte=1) #获取id大于或等于1的值
#selete * from Author where id >= 1
Author.objects.filter(id_lt=10) #获取id小于10的值
#selete * from Author where id < 10
Author.objects.filter(id_lte=10) #获取id小于或等于10的值
#selete * from Author where id <= 10
Author.objects.filter(id_lt=10, id_gt=1) #获取id大于1且小于10的值
#selete * from Author where id < 10 and id > 1
Author.objects.filter(id_in=[11,22,33]) #获取id大在11、22、33中的值
#selete * from Author where id in (11,22,33)
Author.objects.exclude(id_in=[11,22,33]) #not in
#selete * from Author where id not in (11,22,33)
Author.objects.filter(name_contains="ven") #contains(和数据库中like语法相同)
#selete * from Author where name like '%ven%'
Author.objects.filter(name_icontains="ven") #contains大小写不敏感
Author.objects.filter(name_regex="^ven") #正则匹配
Author.objects.filter(name_iregex="^ven") #正则匹配,忽略大小写
Author.objects.filter(age_range=[10,20]) #范围 between and
# startswith, istartswith, endswith, iendswith
# 以什么开始,以什么结束,和上面一样带i的是大小写不敏感的,其实不带i的也忽略大小写
Author.objects.filter(name='seven').order_by('id') # asc 升序
Author.objects.filter(name='seven').order_by('-id') # desc 降序
Author.objects.all()[10,20] # 切片 取所有数据的10-20条,下标从0开始,不能为负数,
# 可以实现分页
# 手动分页
page 页码
per_page 每页数量 = 5
第1页(page=1):0-4 => [0:5]
第2页(page=2):5-9 => [5:10]
第3页(page=3):10-14 => [10:15]
第4页(page=4):15-19 => [15:20] ...
每一页数据范围
[(page-1)*per_page:page*per_page]
#聚合
使用aggregate()函数返回聚合函数的值
Avg: 平均值,Count:数量,Max:最大,Min:最小,Sum:求和
from django.db.models import Count,Min,Max,Sum
Author.objects.aggregate(Max('age'))
6. Django模型进阶
多模块关联关系
关联分类
- ForeignKey:一对多,将字段定义在多的端中
- ManyToM案由Field:多对多,将字段定义在两端的任意一端中
- OneToOneField:一对一,将字段定义在任意一端中
7. Django视图
Django中的视图是要用来接受web请求,并做出响应
视图的本质就是一个Python中的函数
视图的响应分为两大类
以Json数据形式返回(JsonResponse)
以网页的形式返回
重定向到另一个网页(HttpResponseRedirect)
错误视图(4xx,5xx)(HttpResponseNotFound,HttpResponseForbidden,HttpResponseNotAllowed等)
试图响应过程:
浏览器输入->urls路由匹配->视图响应->回馈到浏览器
视图参数:
一个HttpRequest的实例,一般命名为Request
通过url正则表达式传递过来的参数
位置:
通常在应用下的views.py中定义
错误视图:404视图(页面没找到),400视图(客户端操作错误),500(服务器内部错误)
7.1. HttpRequest
服务器在接受到Http请求后,会根据报文创建HttpRequest对象
视图中的第一个参数就是HttpRequest对象
Django框架接收到的Http请求之后会将Http请求包装为HttpRequest对象,之后传递给视图。
属性: path 请求完整的路径
method 请求的方法,常用GET,POST
GET 类似字典的参数,包含了get的所有参数
POST 类似字典的参数,包含了post的所有参数
FILES 类似字典的参数,包含了上传的文件
COOKIES 字典,包含了所有COOKIE
session 类似字典,表示会话
META['REMOTE_ADDR']
方法: is_ajax() 判断是否是ajax(),通常用在移动端和JS中
get_full_path() 返回包函数参数字符串的请求路径
QueryDict:类字段的对象
类似字典的数据结构。与字典的区别:可以存在相同的键。
QueryDict中获取数据的方式
dict['uname']或dict.get('uname')
获取指定key对应的所有值
dict.getlist('uname')
7.2. HttpResponse
服务器返回给客户端的数据
HttpResponse由程序员自己创建:
不使用模版,直接调用HttpResponse(),返回HttpResponse对象。
调用模版,进行渲染。
使用render
render(request,template_name[,context])
request 请求体对象
template_name 模版路径
属性: content 返回的内容
charset 编码格式
status_code 响应状态码(2xx,3xx,4xx,5xx)
方法: write(xxx) 直接写出文本
flush() 冲刷缓冲区
set_cookie(key,value='xxx',max_age=None) 设置cookie
delete_cookie(key) 删除cookie
HttpResponse子类
HttpResponseRedirect
响应重定向:可以实现服务器内部跳转
return HttpResponseRedict(' ')
使用的时候推荐使用反向解析
JsonResponse
返回Json数据的请求,通常用在异步请求上
JsonResponse(dict)
返回json数据时,Content-type时application/json
8. Django会话技术Cookie&Session
8.1. Cookie
理论上,一个用户的所有请求操作都应该属于同一个回话,而另一个用户的所有请求操作则应该属于另一个回话,二者不能混淆,而Web应用程序是使用HTTP协议传输数据的。HTTP协议是无状态的协议。一旦数据交换完毕,客户端与服务器的连接就会关闭,再次交换数据需要建立新的连接。这就意味着服务器无法从连接上跟踪会话。要跟踪该会话,必须引用一种机制。
Cookie就是这样一种机制。他可以弥补HTTP协议无状态的不足。在Session出现之前,基本上所有的网站都采用Cookie来跟踪会话。
Cookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容。
由于HTTP是一种无状态的协议,服务器单从网络连接上无从知道客户身份。怎么办呢?就给客户端们颁发一个通行证,每人一个,无论谁访问都必须携带自己的通行证。这样服务器就能从通行证上确认客户身份了。这就是Cookie的工作原理。
Cookie本身由服务器生成,通过Response将Cookie写到浏览器上,下一次访问,浏览器会根据不要的规则携带Cookie过来。
注意:Cookie不能跨浏览器,一般不跨域
设置Cookie(使用response设置):
response.set_cookie(key,value[,max_age=None,expires=None])
max_age:整数 单位为秒,指定Cookie过期时间
设置为None:浏览器关闭失效,默认值
expires:指定过期时间,还支持datetime或timedelta,还可以指定一个具体日期时间
expires=datetime.datetime(2024,1,1,2,3,4)
或 datetime.datetime.now() + datetime.timedelta(days=10)
注意:max_age和expries两个选一个指定
response.set_cookie('username',username,max_age=10)
response.set_cookie('username',username1,expires=d)
获取Cookie(使用request获取):
request.COOKIES.get('username')
删除Cookie(使用response删除):
response.delete_cookie('username')
cookie存储到客户端
优点:
数据存在客户端,减轻服务器端的压力,提高网站的性能
缺点:
安全性不高,在客户端很容易被查看或破解用户会话信息
8.2. Session
服务器端会话技术,依赖于Cookie
Django中启用SESSION
settings中
INSTALLED_APPS:
'django.contrib.sessions'
MIDDLEWARE:
'django.contrib.session.middleware.SessionMiddleware'
基本操作
设置Session的值(使用request设置)
request.session['user_id'] = user.id
request.session.set_expiry(86400) #设置过期时间
获取Session的值
get(key,default=None) 根据键获取会话的值
username = request.session.get("user_id") 或
session_name = request.session["session_name"]
删除Session的值
# 获取当前请求的session的key
session_key = request.session.session_key
del request.session[session_key]
# request.session.delete(session_key)
fluse()删除当前会话数据并删除会话的Cookie
clear()清除所有会话
数据存储到数据库中会进行编码,使用的是Base64
每个HttpRequest对象都有一个session属性,也是一个类字典对象
9. CSRF
- CSRF全拼为Cross Site Request Forgery,跨站请求伪造
- CSRF指攻击者盗用了你的身份,以你的名义发送恶意请求
包括以你的名义发送邮件,发消息,盗取你的账号,甚至购买商品,虚拟货币转账...
- 造成的问题:个人隐私泄露以及财产安全
9.1. 防止CSRF
- Django下的CSRF预防机制
Django第一次响应来自某个客户端的请求时,会在服务器端随机生成一个token,把这个token放在Cookie里。然后每次POST请求都会带上这个tooken,这样就能避免被CSRF攻击。
- 在Post请求时,表单中添加{% csrf_token %}
<form action='' method='post'>
{% csrf_token %}
...
</form>
10. Django静态文件、媒体文件、文件上传
10.1. 静态文件和媒体文件
- 媒体文件:用户上传的文件,叫做media
- 静态文件:存放在服务器的css.js,image等 叫做static
10.1.1. 静态文件
首先确保django.contrib.staticfiles在 INSTALLED_APPS中
在settings中定义 STATIC_URL
STATIC_URL = '/static'
在你app的static目录中存放静态文件
如果有别的静态文件,不在app下的static目录下,可以通过STATICFILES_DIRS来指定额外的静态文件搜索目录
STATICFILES_DIRS = [
os.path.join(BAST_DIR,"static"),
...
]
在模版中使用load标签去加载静态文件
{% load static %}
<img src="{% static "App/example.jpg" %}" />
10.1.2. 媒体文件
在settings中配置 MEDIA_ROOT
MEDIA_Root = os.path.join(BASE_DIR,"media")
10.2. 文件上传
文件上传要求form表单存在enctype="multipart/form-data"属性,并且提交方法是post
<form enctype="multipart/form-data" action="/uploadFile/" method="post">
<input type="file" name="myfile" />
<br/>
<input type="submit" value="upload" />
</form>
最简单的文件上传:
def file_upload(request):
if request.method == "POST":
myFile = request.FILES.get("myfile",None)
if not myFile:
return HttpResponse("no files for upload")
file_path = os.path.join(settings.MEDIA.ROOT,'1.jpg')
with open(file_path,'ab') as fp:
for part in myFile.chunks():
fp.writer(part)
return HttpResponse("上传成功!")
else:
return render(request,'index.html')
11. get请求和post请求的区别
11.1. Django请求生命周期流程图
11.2. 请求的目的
GET请求:主要用于从指定的资源请求数据。它通常用于查询操作,不会对服务器上的数据进行修改
POST请求:用于向指定的资源提交要被处理的数据。它通常用于创建新的资源或更新资源
11.3. 请求参数的传递方式
GET请求:参数通常附加在URL的查询字符串中(即URL的"?"后面),并且可以通过浏览器的历史记录或书签进行保存和分享。但是,由于URL的长度限制和参数可见性,GET请求不适合传递大量数据或敏感数据。
POST请求:参数通常包含在请求体中,通过HTTP消息头中的Content-Type来指定数据格式(如application/x-www-form-urlencoded、application/json等)。POST请求可以传递大量数据,且数据不会在URL中显示,相对更加安全。
11.4. 安全性
虽然POST请求的参数不在URL中显示,相对于GET请求来说更加安全,但这并不意味着POST请求本身就更安全。例如,POST请求的参数仍然可以通过HTTP消息体被截获。真正的安全性需要依赖于HTTPS等加密协议。
此外,由于GET请求的参数直接暴露在URL中,因此它不适合传递敏感信息(如密码)。而POST请求的参数在请求体中,相对来说更加安全。