会话保持
会话
- 从打开浏览器访问一个网站,到关闭浏览器结束此次访问,称之为一次会话
- HTTP协议是无状态的,导致会话状态难以保护
- cookies和session就是为了保持会话状态而诞生的两个储存技术
Cookies
cookies是保存在客户端浏览器上的存储空间
- cookies在浏览器上是以键值对的形式进行存储的,键和值都是ASCII字符串的形式存储(没有中文)
- 是有存储周期的
- cookies中的数据都是按域存储隔离的,不同域之间无法访问
- cookies的内部数据会在每次访问此网址时都会携带到服务器端,如果+ cookies过大会降低响应速度
-
使用 HttpResponse.set_cookie(key,value='', max_age = None, expires = None)
-
删除和获取
- 删除
HttpResponse.delete_cookie(key) 删除指定key的cookie,如果没有不会发生 - 获取
request.COOKIES cookies字典 request.COOKIES.get(key) 温柔点的取值 -
加盐 salt: 加密盐 -
举例
-
视图view.py from django.shortcuts import render, redirect, HttpResponse, reverse
from django.http import JsonResponse
def login_auth(func):
def inner(request,*args,**kwargs):
target_url = request.get_full_path()
if request.COOKIES.get('username'):
res = func(request,*args,**kwargs)
return res
else:
return redirect('/login/?next=%s'%target_url)
return inner
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
if username == '123' and password == '123':
next_url = request.GET.get('next')
if next_url:
obj = redirect(next_url)
else:
obj = redirect('/home/')
obj.set_cookie('username','123')
return obj
return render(request,'login.html')
@login_auth
def home(request):
return HttpResponse('home页面,只有登录之后才能进来')
@login_auth
def index(request):
return HttpResponse('index页面,只有登录之后才能进来')
@login_auth
def login_out(request):
obj = redirect('/login/')
obj.delete_cookie('username')
return obj
-
login.html <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<h1 class="text-center">登录</h1>
<form action="" method="post">
{% csrf_token %}
<p>username:<input type="text" name="username" class="form-control"></p>
<p>password:<input type="text" name="password" class="form-control"></p>
<input type="submit" class="btn btn-success">
</form>
</body>
</html>
Session
session数据是保存在服务端的,给客户端返回的是一个随机字符串客户端 sessionid:随机字符串 浏览器向服务器提交数据,然后生成session存在数据库,并将sessionid 返回给浏览器,然后浏览器将sessionid作为cookie保存。每个客户端在服务器端有一个独立的session
-
session配置
-
在INSTALLED_APPS中添加django.contrib.sessions -
在MIDDLEWARE中添加django.contrib.sessions.middleware.SessionMiddleware -
修改sessionid的名字: SESSION_COOKIE_NAME = "mysession" -
settings.py其余配置
SESSION_COOKIE_NAME = "sessionid"
SESSION_COOKIE_PATH = "/"
SESSION_COOKIE_DOMAIN = None
SESSION_COOKIE_SECURE = False
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_AGE = 1209600
SESSION_EXPIRE_AT_BROWSER_CLOSE = False
SESSION_SAVE_EVERY_REQUEST = False
注意:
- 在settings.py文件任意位置(推荐底部,方便查找)添加即可
- 如果设置的是默认参数,那么可以比用添加到 settings.py中,比如说我想设置Session的失效日期为1天,那么我只需要在settings.py文件下添加·SESSION_COOKIE_AGE = 86400即可。
- ESSION_SAVE_EVERY_REQUEST = True和SESSION_EXPIRE_AT_BROWSER_CLOSE = True 需同时设置,否则会导致过期时间无法生效
-
数据库迁移命令 在默认情况下操作session的时候需要django默认的一张django_session表 python manage.py makemigrations
python manage.py migrate
-
session的使用 session对象是一个类似于字典的sessionstore类型的对象,可以用类似于字典的方式操作 session能存储字符串,整形,字典,列表等
-
session的保存位置 session是保存在服务端的 但是session的保存位置可以有多种选择
-
session相关方法
request.session['k1']
request.session.get('k1',None)
request.session['k1'] = 123
request.session.setdefault('k1',123)
del request.session['k1']
request.session.keys()
request.session.values()
request.session.items()
request.session.iterkeys()
request.session.itervalues()
request.session.iteritems()
request.session.session_key
request.session.clear_expired()
request.session.exists("session_key")
request.session.delete()
request.session.flush()
这用于确保前面的会话数据不可以再次被用户的浏览器访问
例如,django.contrib.auth.logout() 函数中就会调用它。
request.session.set_expiry(value)
* 如果value是个整数,session会在些秒数后失效。
* 如果value是个datatime或timedelta,session就会在这个时间后失效。
* 如果value是0,用户关闭浏览器session就会失效。
* 如果value是None,session会依赖全局session失效策略。
-
Django中的Session配置 1. 数据库Session
SESSION_ENGINE = 'django.contrib.sessions.backends.db'
1. 缓存Session
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
SESSION_CACHE_ALIAS = 'default'
1. 文件Session
SESSION_ENGINE = 'django.contrib.sessions.backends.file'
SESSION_FILE_PATH = None
1. 缓存+数据库
SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'
1. 加密Cookie Session
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'
其他公用设置项:
SESSION_COOKIE_NAME = "sessionid"
SESSION_COOKIE_PATH = "/"
SESSION_COOKIE_DOMAIN = None
SESSION_COOKIE_SECURE = False
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_AGE = 1209600
SESSION_EXPIRE_AT_BROWSER_CLOSE = False
SESSION_SAVE_EVERY_REQUEST = False
-
session的其他问题
- Django_session表是单表设计,随着用户增多,内容会慢慢增加的,而且过期与删除后不会自动删除数据
- 可以每晚执行
python mange.py clearsessions 【可以删除已经过期的session数据】
缓存
-
缓存
-
定义:缓存是一类可以更快的读取数据的介质的统称,也指其他可以加快数据读取的存储方式,一般用来存储临时数据,常用介质是读取速度很快的内存 -
意义:视图渲染有一定的成本,数据库的频繁查询过高;所以对于低频变动的页面可以考虑使用缓存技术,减少实际渲染次数,用户拿到响应的时间成本会更低 -
案例分析: from django.shortcuts import render
def index(request):
book_list = Book.objects.all()
return render(request,'index.html',local())
-
优化思想:(转至官网) 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中设置缓存 - 数据库缓存
-
将缓存的数据存储在数据库中 -
说明:尽管存储的介质没有更换,但是当把一次负责查询的结果直接存储到另一张表里,比如多个条件的过滤查询结果,可避免重复进行复杂查询,提升效率。 -
设置settings.py,添加CACHES配置 CACHES = {
'default':{
'BACKEND':'django.core.cache.backends.db.DatabaseCache',
'LOCATION':'my_cache_table',
'TIMEOUT':300
'OPTIONS':{
'MAX_ENTRIES':300,
'CULL_FREQUENCY':2
}
}
}
-
注:数据库缓存所使用的数据表需要手动创建,进入django shell执行python manage.py createcachetable,表名为CACHES里面设置的表名 -
数据库迁移后会在数据库中自动生成my_cache_table数据表,数据表中字段:
- cache_key: 缓存的键
- value: 缓存的值
- expires: 缓存的过期时间
-
django中设置缓存 - 本地内存缓存
-
django中设置缓存 - 文件系统缓存
-
django中使用缓存 - 整体缓存策略
-
在视图函数中:将整个视图函数全部缓存到数据库中,如需对某个视图进行增加缓存,直接在该视图上使用cache_page装饰器即可 from django.views.decorators.cache import cache_page
@cache_page(30) -> 单位s,当前视图缓存有效期
def my_view(request):
-
逻辑:第一次请求时将该视图的整个response存入到缓存中,下一次请求时就先检查缓存中是否有需要的response,如果有则不再进入视图函数中处理。 -
在路由中:在需要增加缓存的视图调用位置增加缓存 from django.views.decorators.cache import cache_page
urlpatterns = [
path('page/',cache_page(60)(my_view)),
]
-
缺点:
- 当对整个视图函数进行缓存后,下一次请求时,缓存未过期,请求数据会直接走缓存,如果视图函数中有相关权限校验,则无法进行校验(如:博客网站,博主访问后会将私有博客、公有博客一并进入缓存,访客直接访问的话就不会走视图函数进行身份验证,也能访问到博客的私有博客);
- 删除缓存成本过高,几乎无法得知缓存的key,无法进行主动删除,容易导致出现新旧数据不一致的情况(编辑后的数据无法及时更新到缓存中去)
-
django中使用缓存 - 局部缓存
-
使用缓存API引入
-
方式一:使用caches[‘CACHE配置key’] 导入具体对象 from django.core.cache import caches
cache1 = caches['default']
cache2 = caches['myalias']
-
方式二:直接导入CACHES配置项中的‘default’项:from django.core.cache import cache -
缓存API相关方法:
作用 | 参数 | 返回值 |
---|
cache.set(key,value,timeout) | 存储缓存 | key : 缓存的key,字符串类型 value : python对象 timeout : 缓存存储时间(s),默认为CACHES中的TIMEOUT值 | cache.get(key) | 获取缓存 | key : 缓存的key,字符串类型 | cache.add(key, value) | 存储缓存,只在key不存在时生效 | key : 缓存的key,字符串类型 value : python对象 | cache.get_or_set(key,value,timeout) | 如果未获取到数据则执行set操作 | key : 缓存的key,字符串类型 value : python对象 timeout : 缓存存储时间(s),默认为CACHES中的TIMEOUT值 | cache.set_many(dict,timeout) | 批量存储缓存 | dict : 缓存的key和value的字典 timeout : 缓存时间(s) | cache.get_many(key_list) | 批量获取缓存 | key_list : 包含key的列表 | cache.delete(key) | 删除key的缓存数据 | key : 缓存的key,字符串类型 | cache.delete_many(key) | 批量删除缓存 | key_list : 包含key的列表 |
-
浏览器缓存策略
|