目录
- cookie与session
- Django操作cookie
- session操作
- 视图函数CBV添加装饰器的三种方式
1、cookie与session
网站没有保存用户功能的需求,所有用户访问返回结果都是一样的:新闻、博客、文章。
需要保存用户信息的网站:淘宝、支付宝
cookie:保存在客户端浏览器上的信息都可以称之为cookie,一般以k:v键值对存储。(当用户第一次登陆成功之后,将用户的用户名密码返回给用户浏览器,让用户浏览器保存在本地,之后访问网站的时候浏览器自动将保存在浏览器上的用户名和密码发送给服务器,服务器端获取之后会自动验证。)session:数据是保存在服务端的,一般也是以k:v键值对存储。(当用户登录之后,服务器产生一个随机字符串给客户端浏览器保存着,之后访问服务端的时候都带着该随机字符串,服务端去数据库中对比是否有相应的随机字符串从而获取到对应的用户信息。)token:服务端不再保存数据,登录成功之后,用自己定制的加密方式对内容进行加密处理。将加密后的结果拼接在内容后面,一起发送给客户端浏览器存储,当用户第二次登录时,服务端自动切取前面一段信息再次加密,加密后与浏览器之前存储的拼接内容尾部的密文一起比对校验。
2、Django操作cookie
虽然cookie是服务端告诉客户端浏览器需要保存内容,但是客户端浏览器可以选择拒绝保存,如果浏览器选择禁止保存cookie,那么只要是需要记录用户状态的网站登录功能都无法使用了。
设置cookie:obj.set_cookie(key,value) 加盐处理:obj.set_signedcookie(key,value,salt='盐')获取cookie:request.COOKIES.get(key) request.get_signed_cookie(key,salt='盐')设置cookie超时时间:obj.set_cookie('username','jack',max_age=3或者expires=3)删除cookie:obj.delete_cookie('username')
urls.py文件:
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^login/',views.login),
url(r'^home/',views.home),
url(r'^index/',views.index),
url(r'^func/',views.func),
# 注销功能
url(r'^logout/',views.logout)
]
views.py文件:
from django.shortcuts import render,HttpResponse,redirect
# Create your views here.
# 校验用户是否登录的装饰器(用户登录之后才能访问视图函数)
# def login_auth(func):
# def inner(*args,**kwargs):
# res = func(*args,**kwargs)
# return res
# return inner
def login_auth(func):
def inner(request,*args,**kwargs):
# 拿到用户上一次想访问的url(跳转之前所访问的url)
target_url = request.get_full_path()
if request.COOKIES.get('username'):
return func(request,*args,**kwargs)
else:
return redirect('/login/?next={}'.format(target_url))
return inner
def login(request):
if request.method=='POST':
username = request.POST.get('username')
password = request.POST.get('password')
if username=='jack' and password=='123':
# 获取用户跳转前访问的url
target_url = request.GET.get('next') # 这个结果有可能是None
if target_url:
obj = redirect(target_url)
else:
# 保存用户登录状态
obj = redirect('/home/')
# 让浏览器记录cookie数据
obj.set_cookie('username','jack',max_age=3,expires=3)
# max_age设置超时时间,这里设置的是3秒后过期,expires参数主要是针对IE浏览器
# 如果登陆成功,则跳转到一个登陆成功之后才能看到的页面
# 如果登陆成功,则跳转到一个登陆成功之后才能看到的页面
return obj
return render(request,'login.html')
@login_auth
def home(request):
# 获取cookie信息,判断是否正确
if request.COOKIES.get('username')=='jack':
return HttpResponse('home page for logging user!')
# 没有登录信息应该跳转到登录页面
return redirect('/login/')
@login_auth
def index(request):
if request.COOKIES.get('username')=='jack':
return HttpResponse('index page for logging user!')
return redirect('/login/')
@login_auth
def func(request):
if request.COOKIES.get('username')=='jack':
return HttpResponse('func page for logging user!')
return redirect('/login/')
@login_auth
def logout(request):
obj = redirect('/login/')
obj.delete_cookie('username') # 删除cookie(注销功能)
return obj
login.html页面
<body>
<form action="" method="post">
<p>username:<input type="text" name="username"></p>
<p>password:<input type="password" name="password"></p>
<input type="submit">
</form>
</body>
![f2b20337e676386920a7b65176fd6822.png](https://i-blog.csdnimg.cn/blog_migrate/c7253f0b497964e4dbe9c157855579d2.jpeg)
3、session操作
session数据是保存在服务端的,给客户端返回的是一个随机字符串(sessionid键)
默认情况下操作session时需要Django默认创建的一张表django_session(在运行数据库迁移命令后,点击db.sqlite3就能看到),django_session表中的数据条数是取决于浏览器的,同一个计算机上同一个浏览器只会有一条数据生效,用另一个浏览器访问就又会生成一条数据,当session过期的时候可能会短暂的出现多条数据对应一个浏览器,该现象不会持续很久,内部会自动识别过期的数据并清除。
![eb14a7f5745b7b4c36cc7e97f3b86b17.png](https://i-blog.csdnimg.cn/blog_migrate/8007ad16d83405ea1202bc8f51c65141.png)
Django默认session的过期时间是14天。
设置session:request.session['key'] = value获取session:request.session.get('key')设置过期时间:request.session.set_expiry()
清除session:request.session.delete() # 删除当前会话所有的sessionrequest.session.flush() # 浏览器和服务端都清空,一般用这个
有时候如果多个视图函数都需要使用到一些数据的话,可以考虑保存到django_session表中,方便后续使用。eg:登录验证码。
session是保存在服务器端,但是session的保存位置提供了5种选择:
1. 数据库Session
SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默认)
2. 缓存Session
SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 引擎
SESSION_CACHE_ALIAS = 'default' # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置
3. 文件Session
SESSION_ENGINE = 'django.contrib.sessions.backends.file' # 引擎
SESSION_FILE_PATH = None # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir()
4. 缓存+数据库
SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' # 引擎
5. 加密Cookie Session
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies' # 引擎
urls.py文件:
# session操作
url(r'^set_session/',views.set_session),
url(r'^get_session/',views.get_session),
url(r'^del_session/',views.del_session)
views.py文件:
def set_session(request):
request.session['hobby']='learning'
# request.session['hobby1']='learning1'
# request.session['hobby2']='learning2'
# set_expiry后可以放四种类型的参数:
# 1、整数,多少秒
# 2、日期对象,到指定日期就失效
# 3、数字0,一旦当前浏览器窗口关闭会立即失效
# 4、不写,失效时间取决于Django内部全局session默认失效时间14天
request.session.set_expiry()
'''
设置session内部发生的事情:
1、Django内部自动生成一个随机字符串
2、Django内部自动将随机字符串和对应的数据存储到django_session表中
2.1、在内存中产生操作数据的缓存
2.2、在响应结果Django中间件的时候才真正的操作数据库
3、将产生的随机字符串返回给客户端浏览器保存
'''
return HttpResponse('hhh')
def get_session(request):
print(request.session.get('hobby'))
# print(request.session)
# print(request.session.get('hobby'))
# print(request.session.get('hobby1'))
# print(request.session.get('hobby2'))
'''
获取session内部发生的事情:
1、自动从浏览器请求中获取session_id对应的随机字符串
2、用该随机字符串去django_session表中查找对应的数据
3、如果有匹配的数据,则将对应的数据取出并以字典的形式封装到request.session中,如果没有匹配的数据,则request.session.get()返回none
'''
return HttpResponse('哈哈哈')
def del_session(request):
# request.session.delete()
request.session.flush()
return HttpResponse('清除session:浏览器和服务端都清空')
![59df166ef4ffe73a96d18cd2d45b90f5.png](https://i-blog.csdnimg.cn/blog_migrate/395495e9f27d9458e03ce07133897110.jpeg)
4、视图函数CBV添加装饰器的三种方式
urls.py文件:
# CBV添加装饰器
url(r'^mylogin/',views.MyLogin.as_view())
views.py文件:
from django.views import View
from django.utils.decorators import method_decorator
'''
CBV中Django不建议你直接给类的方法加装饰器
'''
# 装饰器方式2,可以针对不同的方法添加不同的装饰器,扩展性强:
# @method_decorator(login_auth,name='get')
# @method_decorator(login_auth,name='post')
class MyLogin(View):
# 装饰器方式3:它会直接作用于当前类里面的所有方法
@method_decorator(login_auth)
def dispatch(self, request, *args, **kwargs): # 重写dispatch方法
pass
# 装饰器方式1:
# @method_decorator(login_auth)
def get(self,request):
return HttpResponse('get请求')
def post(self,request):
return HttpResponse('post请求')