Cookie和Session

Cookie的由来:

因为HTTP协议是无状态;无状态也就是每次的请求都是独立的,比如你不用登录你的账户,你就可以进入需要账户的网站一样,因为对于服务器来说,每次请求都是全新的;

状态也可以理解为B和S之间的通信产生的数据;无状态则表示数据不会被保留;但是在某些场合下,我们是需要用到这些数据;因此我们需要保持状态,所以cookie就产生了;

Django中操作Cookie:

获取Cookie

request.COOKIES['key']
request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
# cookie装饰器
# def crwapper(func):
# 	@wraps(func)
# 	def inner(request,*args,**kwargs):  #被装饰器装饰的函数的参数;一个形参
# 		ret = request.get_signed_cookie("is_login", default="0", salt='加盐')
# 		if ret == "4":
# 			ret_new = func(request)
# 			return ret_new
# 		else:
# 			path = request.path_info   #获得当前的路径;不带条件
# 			request.get_full_path()
# 			print(path)
# 			return redirect("/login/?next={}".format(path))
# 	return inner

参数:

  • default: 默认值
  • salt: 加密盐
  • max_age: 后台控制过期时间

 

设置Cookie:

rep = HttpResponse(...)
rep = render(request, ...)
rep = redirect(...)
rep.set_cookie(key,value,...)
rep.set_signed_cookie(key,value,salt='加密盐', max_age=None, ...)

 注意:设置cookie的时候是用响应来设置

  • key, 键
  • value='', 值
  • max_age=None, 超时时间

 

rep.set_signed_cookie("is_login","4",salt='加盐',max_age =10)  #max_age 为cookie存在的秒数

删除Cookie:

ef logout(request):
    rep = redirect("/login/")
    rep.delete_cookie("user")  # 删除用户浏览器上之前设置的usercookie值
    return rep

  

Cookie版登陆校验:

# cookie版
# def login(request):
# 	# GET请求就是请求获取页面;或是搜索引擎
# 	# username_list=[]
# 	# pwd_list = []
# 	error_msg=""
# 	if request.method == "POST":
# 		# 否则的话就是POST请求,是提交表单等数据给服务器;request.POST获得请求的数据
# 		ret = request.POST
# 		username = ret.get("username", None)
# 		password = ret.get("pwd", None)
#
# 		# 把/login/?next=/index/ 条件拿到
#
# 		path =request.get_full_path()   #获得路径 加 条件;
# 		print(path)  #/login/?next=/index/
# 		url = request.GET.get("next")   #动态的路径
#
# 		# obj = models.UserInfo.objects.all()
# 		# for i in obj:
# 		# 	username_list.append(i.name)
# 		# 	pwd_list.append(i.password)
# 		# if username in username_list and password in pwd_list:
# 		if username=="alex" and password=="123":
# 		# return HttpResponse("登录成功")
# 		# 给浏览器发送一个响应,带cookie
# 			if url:
# 				rep = redirect(url)   #响应的对象
# 			else:
# 				rep = redirect("/login_home/")  # 响应的对象
# 			# rep.set_cookie("is_login","1")
# 			rep.set_signed_cookie("is_login","4",salt='加盐',max_age =10)  #max_age 为cookie存在的秒数
# 			# return redirect("http://www.baidu.com")
# 			return rep
# 		else:
# 			error_msg="账号或者密码错误"
# 	#动态网页,替换的功能
# 	return render(request, 'login.html',{"error":error_msg})

  

Session

由于cookie本身是保存在客户端上的(也就是浏览器上的),容易被拦截或窃取;同时最大只能支持4096个字节;

所以出现了Session,Session是保存在服务器端的,有较高的安全性,但是基于HTTP协议的无状态的特性,要用Cookie起到桥接的作用;

因此 现在多用 Session 和 Cookie 结合使用;Cookie和Session其实是共通性的东西,不限于语言和框架

 其实 存 和 取 是很简单的,生成随机的字符串,然后把字符串当作K,存的数据作为一个大字典;按照 键值对的形式保存在数据库中;然后 把随机的字符串当作cookie返回给浏览器;这系列的过程全部由Django帮你做;你只需要存和取就行了

Django中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()

# 会话session的key
request.session.session_key

# 将所有Session失效日期小于当前日期的数据删除
request.session.clear_expired()

# 检查会话session的key在数据库中是否存在
request.session.exists("session_key")

# 删除当前会话的所有Session数据
request.session.delete()
  
# 删除当前的会话数据并删除会话的Cookie。
request.session.flush() 
    这用于确保前面的会话数据不可以再次被用户的浏览器访问
    例如,django.contrib.auth.logout() 函数中就会调用它。

# 设置会话Session和Cookie的超时时间
request.session.set_expiry(value)
    * 如果value是个整数,session会在些秒数后失效。
    * 如果value是个datatime或timedelta,session就会在这个时间后失效。
    * 如果value是0,用户关闭浏览器session就会失效。
    * 如果value是None,session会依赖全局session失效策略。

  

 Session 和 cookie 结合的登录校验

# session和cookie结合版的
def login(request):
	# GET请求就是请求获取页面;或是搜索引擎
	# username_list=[]
	# pwd_list = []
	# 将所有的session 失效日期 小于当前的日期的数据 删除;也就是将过期的数据删除;
	request.session.clear_expired()
	error_msg = ""
	if request.method == "POST":
		# 否则的话就是POST请求,是提交表单等数据给服务器;request.POST获得请求的数据
		ret = request.POST
		username = ret.get("username", None)
		password = ret.get("pwd", None)

		# 把/login/?next=/index/ 条件拿到

		path = request.get_full_path()  # 获得路径 加 条件;
		print(path)  # /login/?next=/index/
		url = request.GET.get("next")  # 动态的路径

		# obj = models.UserInfo.objects.all()
		# for i in obj:
		# 	username_list.append(i.name)
		# 	pwd_list.append(i.password)
		# if username in username_list and password in pwd_list:
		if username == "alex" and password == "123":
			# return HttpResponse("登录成功")
			# 给浏览器发送一个响应,带cookie
			if url:
				rep = redirect(url)  # 响应的对象
			else:
				rep = redirect("/login_home/")  # 响应的对象

			# 设置一下 session ,生成一段字符串,然后把字符串当做K,
			# 把存的数据放在大字典里面,大字典当做v,按K-V的形式保存在数据库里面;
			# Django自动的;帮你生成一段字符串;按K-V的形式保存在数据库里面;

			request.session["is_login"] = "1"
			# Object of type 'datetime' is not JSON serializable;需要自定义的序列化
			# day_time = datetime.datetime.utcnow().replace(tzinfo=pytz.utc) + datetime.timedelta(days=3)
			# request.session.set_expiry(day_time)
			request.session.set_expiry(7 * 24 * 60 * 60)  # 7s后session失效;失效是指浏览器上的cookie没有了,但是数据库里面还有;
			return rep
		else:
			error_msg = "账号或者密码错误"
	# 动态网页,替换的功能
	return render(request, 'login.html', {"error": error_msg})
# session和cookie装饰器
def crwapper(func):
	@wraps(func)
	def inner(request, *args, **kwargs):  # 被装饰器装饰的函数的参数;一个形参
		ret = request.session.get("is_login", None)
		if ret == "1":
			ret_new = func(request)
			return ret_new
		else:
			path = request.path_info  # 获得当前的路径;不带条件
			request.get_full_path()
			print(path)
			return redirect("/login/?next={}".format(path))

	return inner

注销Session和Cookie

# 注销cookie和session
def logout(requset):
	requset.session.flush()
	return redirect('/login/')

  

Session流程解析

CBV中加装饰器相关:(详细点我)

1. 加在CBV视图的get或post方法上

3. 直接加在视图类上,但method_decorator必须传 name 关键字参数

如果get方法和post方法都需要登录校验的话就写两个装饰器。

# 把上面的session装饰器叫到CBV视图上的方法上
from django.utils.decorators import method_decorator
from django.views import View


# @method_decorator(crwapper,name='post')
class Login(View):

	@method_decorator(crwapper)  # method_decorator实际上就是把第二个参数request传入你的装饰器的作用;
	def post(self, request):

		# 否则的话就是POST请求,是提交表单等数据给服务器;request.POST获得请求的数据
		ret = request.POST
		username = ret.get("username", None)
		password = ret.get("pwd", None)

		# 把/login/?next=/index/ 条件(参数)拿到

		path = request.get_full_path()  # 获得路径 加 条件(参数);
		# request.path_info  获取路径

		print(path)  # /login/?next=/index/
		url = request.GET.get("next")  # 动态的路径

		# obj = models.UserInfo.objects.all()
		# for i in obj:
		# 	username_list.append(i.name)
		# 	pwd_list.append(i.password)
		# if username in username_list and password in pwd_list:
		if username == "alex" and password == "123":
			# return HttpResponse("登录成功")
			# 给浏览器发送一个响应,带cookie
			if url:
				rep = redirect(url)  # 响应的对象
			else:
				rep = redirect("/login_home/")  # 响应的对象

			# 设置一下 session ,生成一段字符串,然后把字符串当做K,
			# 把存的数据放在大字典里面,大字典当做v,按K-V的形式保存在数据库里面;
			# Django自动的;帮你生成一段字符串;按K-V的形式保存在数据库里面;

			request.session["is_login"] = "1"
			# Object of type 'datetime' is not JSON serializable;需要自定义的序列化
			# day_time = datetime.datetime.utcnow().replace(tzinfo=pytz.utc) + datetime.timedelta(days=3)
			# request.session.set_expiry(day_time)
			request.session.set_expiry(7 * 24 * 60 * 60)  # 7s后session失效;失效是指浏览器上的cookie没有了,但是数据库里面还有;
			return rep

	@method_decorator(crwapper)
	def get(self, request):
		request.session.clear_expired()
		return render(request, 'login.html')

  

  

  

自定义分页:

# 分页

# # 获取当前的页码
# page_num = request.GET.get('page')
# page_num = int(page_num)
# print(page_num)
#
# #获得总的数据
#
# total_num = models.Book.objects.all().count()
#
# #每一页呈现的数量
# each_page = 10
#
# #获得总页码
# total_page,n = divmod(total_num,each_page)   # 13//2 --> (6,1)
# if n:
# 	total_page+=1
#
# # 页面上总共展示多少页码
# max_page = 9
#
# # 在页面张展示的页码 小于 页面上总共展示多少页码数的时候:
# if total_page <= max_page:
# 	max_page = total_page
#
# # 最大的一半的页码数
# half_max_page = max_page // 2
#
# page_start = page_num - half_max_page
# page_end = page_num + half_max_page
# # 当开始页 小于1 :
# if page_start <=1:
# 	page_start = 1
# 	page_end = max_page
# # 当最后一页 大于 总页数的时候 :
# if page_end >=total_page:
# 	page_end = total_page
# 	page_start = page_end - max_page +1
#
#
# #每一页呈现的数据 的开始和结束
# data_start = (page_num-1) * each_page
# data_end  = page_num * each_page
#
#
# #这个是每一页呈现的数据
# #左闭右开的
# books = models.Book.objects.all()[data_start:data_end]
#
# #在页面张展示的页码
# total_page_html = []
#
# # 首页
# start_page_html = '<li><a href="/see_book/?page=1">{}</a></li>'.format('首页')
# total_page_html.append(start_page_html)
# # 上一页
# if page_num <= 1:
# 	Previous_page = '<li class="disabled"><a href="#"><span aria-hidden="true">上一页</span></a></li>'
# else:
# 	Previous_page = '<li><a href="/see_book/?page={}"><span aria-hidden="true">上一页</span></a></li>'.format(page_num-1)
# print(page_num-1)
# total_page_html.append(Previous_page)
#
# for i in range(page_start,page_end+1):
# 	if i ==page_num:
# 		page_html = '<li class="active"><a href="/see_book/?page={0}">{0}</a></li>'.format(i)
# 	else:
# 		page_html = '<li><a href="/see_book/?page={0}">{0}</a></li>'.format(i)
# 	total_page_html.append(page_html)
#
# #向下一页
# if page_num >= total_page:
# 	Next_page = '<li class="disabled"><a href="#"><span aria-hidden="true">下一页</span></a></li>'.format(total_page)
# else:
# 	Next_page = '<li><a href="/see_book/?page={}"><span aria-hidden="true">下一页</span></a></li>'.format(page_num+1)
# total_page_html.append(Next_page)
#
# #尾页
# end_page_html = '<li><a href="/see_book/?page={1}">{0}</a></li>'.format('尾页',total_page)
# total_page_html.append(end_page_html)
#
# total_page_html = ''.join(total_page_html)

  

  

原文地址:https://www.cnblogs.com/zenghui-python/p/10931773.html