cookies 和 session

  • 会话 - 从打开浏览器访问一个网站,到关闭浏览器结束此次访问,称之为一次会话
  • HTTP协议是无状态的,导致会话状态难以保持
  • 试想一下,如果不保持会话状态,在电商网站购物的场景
    体验?

Cookies和Session就是为了保持会话状态而诞生的两个存储技术

cookies

  • cookies是保存在客户端浏览器上的存储空间

  • Chrome 浏览器 可能通过开发者工具的 Application >> Storage >> Cookies 查看和操作浏览器端所有的 Cookies 值

  • 火狐浏览器 可能通过开发者工具的 存储 -> Cookie

    • cookies 在浏览器上是以键-值对的形式进行存储的,键和值都是以ASCII字符串的形存储(不能是中文字符串)

    • cookies中的数据是按域存储隔离的,不同的域之间无法访问

    • cookies 的内部的数据会在每次访问此网址时都会携带到服务器端,如果cookies过大会降低响应速度

  • 在Django 设置浏览器的COOKIE 必须通过 HttpResponse 对象来完成

    • 添加、修改COOKIE

      • HttpResponse.set_cookie(key, value=’’, max_age=None, expires=None)
        • key: cookie的名字
        • value: cookie的值
        • max_age: cookie存活时间,秒为单位
        • expires: 具体过期时间
        • 当不指定max_age和expires 时,关闭浏览器时此数据失效
    • 删除COOKIE

      • HttpResponse.delete_cookie(key)
      • 删除指定的key 的Cookie。 如果key 不存在则什么也不发生。
    • 获取cookie

      • 通过 request.COOKIES 绑定的字典(dict) 获取客户端的 COOKIES数据

        1
        2
        value = request.COOKIES.get('cookies名', '默认值')
        print("cookies名 = ", value)
  • 示例

    • 以下示例均在视图函数中调用
    • 添加cookie
      1
      2
      3
      4
      # 为浏览器添加键为 my_var1,值为123,过期时间为1个小时的cookie
      responds = HttpResponse("已添加 my_var1,值为123")
      responds.set_cookie('my_var1', 123, 3600)
      return responds
    • 修改cookie
      1
      2
      3
      4
      # 为浏览器添加键为 my_var1,修改值为456,过期时间为2个小时的cookie
      responds = HttpResponse("已修改 my_var1,值为456")
      responds.set_cookie('my_var1', 456, 3600*2)
      return responds
    • 删除cookie
      1
      2
      3
      4
      # 删除浏览器键为 my_var1的cookie
      responds = HttpResponse("已删除 my_var1")
      responds.delete_cookie('my_var1')
      return responds
    • 获取cookie
      1
      2
      3
      4
      # 获取浏览器中 my_var变量对应的值
      value = request.COOKIES.get('my_var1', '没有值!')
      print("cookie my_var1 = ", value)
      return HttpResponse("my_var1:" + value)

session

  • session又名会话控制,是在服务器上开辟一段空间用于保留浏览器和服务器交互时的重要数据

  • 实现方式

    • 使用 session 需要在浏览器客户端启动 cookie,且用在cookie中存储sessionid
    • 每个客户端都可以在服务器端有一个独立的Session
    • 注意:不同的请求者之间不会共享这个数据,与请求者一一对应
  • Django中配置Session

    • 在 settings.py 文件中
    • 向 INSTALLED_APPS 列表中添加:
      1
      2
      3
      4
      INSTALLED_APPS = [
      # 启用 sessions 应用
      'django.contrib.sessions',
      ]
    • 向 MIDDLEWARE 列表中添加:
      1
      2
      3
      4
      MIDDLEWARE = [
      # 启用 Session 中间件
      'django.contrib.sessions.middleware.SessionMiddleware',
      ]
  • session的基本操作:

    • session对于象是一个类似于字典的SessionStore类型的对象, 可以用类拟于字典的方式进行操作
    • session 只能够存储能够序列化的数据,如字典,列表等。
    1. 保存 session 的值到服务器

      • request.session['KEY'] = VALUE
    2. 获取session的值

      • VALUE = request.session['KEY']
      • VALUE = request.session.get('KEY', 缺省值)
    3. 删除session的值

      • del request.session[‘KEY’]`
  • 在 settings.py 中有关 session 的设置

    1. SESSION_COOKIE_AGE
      • 作用: 指定sessionid在cookies中的保存时长(默认是2周),如下:
      • SESSION_COOKIE_AGE = 60 * 60 * 24 * 7 * 2
    2. SESSION_EXPIRE_AT_BROWSER_CLOSE = True
      设置只要浏览器关闭时,session就失效(默认为False)
  • 注: 当使用session时需要迁移数据库,否则会出现错误

    1
    python3 manage.py migrate
1
2
3
django 原生session 问题:
1,django_session表是 单表设计; 且该表数据量持续增持【浏览器故意删掉sessionid&过期数据未删除】
2,可以每晚执行 python3 manage.py clearsessions 【该命令可删除已过期的session数据】

Cookies vs session

1
2
3
4
5
6
存储位置:
C- 浏览器中 s- 服务器中【mysql】
安全性:
C - 不安全 s- 相对安全一些

不管C还是S , 不要存储敏感数据 【密码】

缓存

什么是缓存?

缓存是一类可以更快的读取数据的介质统称,也指其它可以加快数据读取的存储方式。一般用来存储临时数据,常用介质的是读取速度很快的内存

为什么使用缓存?

视图渲染有一定成本,对于低频变动的页面可以考虑使用缓存技术,减少实际渲染次数

案例分析

1
2
3
4
5
6
from django.shortcuts import render

def index(request):
# 时间复杂度极高的渲染
book_list = Book.objects.all() #-> 此处假设耗时2s
return render(request, 'index.html', locals())

优化思想

1
2
3
4
5
6
7
8
given a URL, try finding that page in the cache

if the page is in the cache:
return the cached page
else:
generate the page
save the generated page in the cache (for next time)
return the generated page

使用缓存场景:博客列表页,电商商品详情页,缓存导航及页脚

Django中设置缓存

Django中提供多种缓存方式,如需使用需要在settings.py中进行配置

  1. 数据库缓存 mysite7 改配置 migrate , 添加缓存配置项 createcachetable

Django可以将其缓存的数据存储在您的数据库中

1
2
3
4
5
6
7
8
9
10
11
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
'LOCATION': 'my_cache_table',
'TIMEOUT': 300, #缓存保存时间 单位秒,默认值为300,
'OPTIONS':{
'MAX_ENTRIES': 300, #缓存最大数据条数
'CULL_FREQUENCY': 2,#缓存条数达到最大值时 删除1/x的缓存数据
}
}
}

创建缓存表

1
python3 manage.py createcachetable
  1. 文件系统缓存
1
2
3
4
5
6
7
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': '/var/tmp/django_cache',#这个是文件夹的路径
#'LOCATION': 'c:\test\cache',#windows下示例
}
}
  1. 本地内存缓存
1
2
3
4
5
6
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'LOCATION': 'unique-snowflake'
}
}

Django中使用缓存

  • 在视图View中使用
  • 在路由URL中使用
  • 在模板中使用

在视图View中使用cache

1
2
3
4
5
from django.views.decorators.cache import cache_page

@cache_page(30) -> 单位s
def my_view(request):
...

在路由中使用

1
2
3
4
5
from django.views.decorators.cache import cache_page

urlpatterns = [
path('foo/', cache_page(60)(my_view) ),
]

在模板中使用

1
2
3
4
5
{% load cache %}        

{% cache 500 sidebar username %}
.. sidebar for logged in user ..
{% endcache %}
  • 缓存api

    作用:局部缓存部分结果

    使用:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    #指定配置引入
    from django.core.cache import caches
    cache1 = caches['myalias']
    cache2 = caches['myalias_2']

    #默认配置引入【指的配置中的default项】 等同于 caches['default']
    from django.core.cache import cache

    #常规命令 set
    #key: 字符串类型
    #value: Python对象
    #timeout:缓存存储时间 默认值为settings.py CACHES对应配置的TIMEOUT
    #返回值:None
    cache.set('my_key', 'myvalue', 30)

    #常规命令 get
    #返回值:为key的具体值,如果没有数据,则返回None
    cache.get('my_key')
    #可添加默认值,如果没取到返回默认值
    cache.get('my_key', 'default值')

    #常规命令 add 只有在key不存在的时候 才能设置成功
    #返回值 True or False
    cache.add('my_key', 'value') #如果my_key已经存在,则此次赋值失效

    #常规命令 get_or_set 如果未获取到数据 则执行set操作
    #返回值 key的值
    cache.get_or_set('my_key', 'value', 10)

    #常规命令 get_many(key_list) set_many(dict,timeout)
    #返回值 set_many:返回插入不成功的key数组
    # get_many:取到的key和value的字典
    >>> cache.set_many({'a': 1, 'b': 2, 'c': 3})
    >>> cache.get_many(['a', 'b', 'c'])
    {'a': 1, 'b': 2, 'c': 3}

    #常规命令 delete
    #返回值 None
    cache.delete('my_key')

    #常规命令 delete_many
    #返回值 成功删除的数据条数
    cache.delete_many(['a', 'b', 'c'])

浏览器中的缓存

浏览器缓存

浏览器缓存分类:

强缓存

不会向服务器发送请求,直接从缓存中读取资源

1,Expires

缓存过期时间,用来指定资源到期的时间,是服务器端的具体的时间点

Expires:Thu, 02 Apr 2030 05:14:08 GMT

Expires 是 HTTP/1 的产物,受限于本地时间,如 果修改了本地时间,可能会造成缓存失效

2, Cache-Control

在HTTP/1.1中,Cache-Control主要用于控制网页缓存。比如当Cache-Control:max-age=120 代表请求创建时间后的120秒,缓存失效

协商缓存

协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程

  1. Last-Modified和If-Modified-Since

    ​ 第一次访问时,服务器会返回

    Last-Modified: Fri, 22 Jul 2016 01:47:00 GMT

    ​ 浏览器下次请求时 携带If-Modified-Since这个header , 该值为 Last-Modified

    ​ 服务器接收请求后,对比结果,若资源未发生改变,则返回304, 否则返回200并将新资源返回给浏览器

    ​ 缺点:只能精确到秒,容易发生单秒内多次修改,检测不到

  2. ETag和If-None-Match

    ​ Etag是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成),只要资源有变化,Etag就会重新生成

    ​ 流程同上

对比 Last-Modified VS ETag

  1. 精度不一样 - Etag 高

  2. 性能上 - Last-Modifi 高

  3. 优先级 - Etag 高