Cookie是浏览器在客户端留下的一段记录,这段记录可以保留在内存或者硬盘上。因为Http请求是无状态的,通过读取cookie的记录,服务器或者客户端可以维持会话中的状态。比如一个常见的应用场景就是登录状态。Django里面,对cookie的读取和设置很简单。Cookie本身的格式类似字典,因此可以通过request的key或者get获取;然后他的设置则是通过response对象的set_cookie设定; 如果要取消cookie,把过期时间设置为当前时间就行了。


获取Cookie:

request.COOKIES['key']request.get_signed_cookie(key,default=RAISE_ERROR,salt='',max_age=None)参数:default:默认值salt:加密盐max_age:后台控制过期时间


设置Cookie:

rep=HttpResponse(...)或rep=render(request,...)rep.set_cookie(key,value,...)rep.set_signed_cookie(key,value,salt='加密盐',...)参数:key,键value='',值max_age=None,超时时间expires=None,超时时间(IErequiresexpires,sosetitifhasn'tbeenalready.)path='/',Cookie生效的路径,/表示根路径,特殊的:跟路径的cookie可以被任何url的页面访问domain=None,Cookie生效的域名secure=False,https传输httponly=False只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)



例1 设置一个login登录界面,一个index登录成功之后的跳转界面,如果没有登录那么自动跳转到登录界面


views.py

defindex(reqeust):#获取当前已经登录的用户v=reqeust.COOKIES.get('username111')ifnotv:returnredirect('/login/')returnrender(reqeust,'index.html',{'current_user':v})

注意Cookie的超时时间有2种方式,一个是直接指定max_age(N秒后超时),一个是指定expires后面跟一个具体的时间对象

httponly可以禁止JavaScript获取这个值,但是实际上没有什么鸟用,chrome或者抓包都能轻松获取所有的cookie



index.html

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title></title></head><body><h2>欢迎登录:{{current_user}}</h2></body></html>


login.html

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title></title></head><body><formaction="/login/"method="POST"><inputtype="text"name="username"placeholder="用户名"/><inputtype="password"name="pwd"placeholder="密码"/><inputtype="submit"/></form></body></html>


例2:

现实生活中,一般是把这个验证cookie的功能写成装饰器,这样直接在其他函数上面调用就行了

把例1改一下

defauth(func):definner(reqeust,*args,**kwargs):v=reqeust.COOKIES.get('username111')ifnotv:returnredirect('/login/')returnfunc(reqeust,*args,**kwargs)returninner@authdefindex(reqeust):#获取当前已经登录的用户v=reqeust.COOKIES.get('username111')returnrender(reqeust,'index.html',{'current_user':v})


例3: 我们知道可以使用fbv或者cbv来路由函数。例2使用了fbv的方式,用cbv也能实现

cbv里面,如果只打算装饰一个方法,那么直接在方法前面加个@method_decorator就行;如果打算装饰这个类里面所有的方法,那么在整个类的最上面进行装饰


views.py

@method_decorator(auth,name='dispatch')classOrder(views.View):#@method_decorator(auth)#defdispatch(self,request,*args,**kwargs):#returnsuper(Order,self).dispatch(request,*args,**kwargs)#@method_decorator(auth)defget(self,reqeust):v=reqeust.COOKIES.get('username111')returnrender(reqeust,'index.html',{'current_user':v})defpost(self,reqeust):v=reqeust.COOKIES.get('username111')returnrender(reqeust,'index.html',{'current_user':v})


urls.py

url(r'^order/',views.Order.as_view()),


例4 我们还可以通过JavaScript或者JQuery来设置Cookie,比如在前面分页的代码基础上,我们增加一个自定义显示行数的功能。


user_list.html 这里下了一个JQuery的插件,这样读取设置cookie比较容易;而且,我们还限制了cookie的使用范围,不是默认的所有范围,而是仅仅局限于/user_list这个路径里面

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title></title><style>.go{width:20px;border:solid1px;color:#66512c;display:inline-block;padding:5px;}.pagination.page{border:solid1px;color:#66512c;display:inline-block;padding:5px;background-color:papayawhip;margin:5px;}.pagination.page.active{background-color:brown;color:white;}</style></head><body><ul>{%foriteminli%}{%include'li.html'%}{%endfor%}</ul><div><selectid="ps"onchange="changePageSize(this)"><optionvalue="10">10</option><optionvalue="30">30</option><optionvalue="50">50</option><optionvalue="100">100</option></select></div><divclass="pagination">{{page_str}}</div><scriptsrc="/static/jquery-1.12.4.js"></script><scriptsrc="/static/jquery.cookie.js"></script><script>$(function(){varv=$.cookie('per_page_count',{'path':"/user_list/`"});console.log(v)$('#ps').val(v);});functionchangePageSize(ths){varv=$(ths).val();console.log(v);$.cookie('per_page_count',v,{'path':"/user_list/"});location.reload();}</script></body></html>



views.py 从前端获取每页行数,实例化的时候传递给我们的分页类

defuser_list(request):current_page=request.GET.get('p',1)current_page=int(current_page)val=request.COOKIES.get('per_page_count',10)val=int(val)page_obj=pagination.Page(current_page,len(LIST),val)data=LIST[page_obj.start:page_obj.end]page_str=page_obj.page_str("/user_list/")returnrender(request,'user_list.html',{'li':data,'page_str':page_str})