Python学习笔记整理总结【Django】:模板语言、分页、Cookie、Session
一、模板语言
1、在前段展示:对象/字典/元组
class Business(models.Model): # id #用默认的自增id列 即:Business中有3列数据(id, caption, code) caption = models.CharField(max_length=32) code = models.CharField(max_length=32,default="SA")
from django.shortcuts import render,HttpResponse,redirect from app01 import models # Create your views here. def business(request): # 以下得到的都是QuerySet类型数据(类似于列表) v1 = models.Business.objects.all() # ①得到的是business obj对象 [obj(id,caption,code),obj(id,caption,code), ] v2 = models.Business.objects.all().values('id','caption') # ②得到的是字典 [{'id':1,'caption': '运维部'},{'id':1,'caption': '运维部'},...] v3 = models.Business.objects.all().values_list('id','caption') # ③得到的是元组 [(1,运维部),(2,开发)] return render(request, 'business.html', {'v1': v1,'v2': v2, 'v3': v3}) #前端的三种形式: # {% for row in v %} # ① <li>{{ row.id }} - {{ row.caption }} - {{ row.code }}</li> # ② <li>{{ row.id }} - {{ row.caption }} - {{ row.code }}</li> # ③ <li>{{ row.0 }} - {{ row.1 }} - {{ row.1 }</li> # {% endfor %}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <h1>业务线列表(对象)</h1> <ul> {% for row in v1 %} <li>{{ row.id }} - {{ row.caption }} - {{ row.code }}</li> {% endfor %} </ul> <h1>业务线列表(字典)</h1> <ul> {% for row in v2 %} <li>{{ row.id }} - {{ row.caption }}</li> {% endfor %} </ul> <h1>业务线列表(元组)</h1> <ul> {% for row in v3 %} <li>{{ row.0 }} - {{ row.1 }}</li> {% endfor %} </ul> </body> </html>
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^business$', views.business), #加上终止符($)防止business匹配完成后以下的business_add不再执行
]
INSTALLED_APPS = [
'app01',
]
2、排序
① forloop.counter 表示循环的次数,它从1开始计数,第一次循环设为1
{% for item in todo_list %} <p>{{ forloop.counter }}: {{ item }}</p> {% endfor %}
② forloop.counter0 表示循环的次数,它从0开始计数,第一次循环设为0
{% for item in todo_list %} <p>{{ forloop.counter0 }}: {{ item }}</p> {% endfor %}
③ forloop.revcounter 示循环中剩下的items数量,第一次循环时设为items总数,最后一次设为1
{% for item in todo_list %} <p>{{ forloop.revcounter }}: {{ item }}</p> {% endfor %}
④ forloop.revcounter0 类似于forloop.revcounter,但它是表示的数量少一个,即最后一次循环时设为0
{% for item in todo_list %} <p>{{ forloop.revcounter0 }}: {{ item }}</p> {% endfor %}
⑤ forloop.first 当第一次循环时值为True,在特别情况下很有用)
{% for object in objects %} {% if forloop.first %}<li class="first">{% else %}<li>{% endif %} {{ object }} </li> {% endfor %}
⑥ forloop.last 当最后一次循环时值为True
{% for link in links %}{{ link }}{% if not forloop.last %} | {% endif %}{% endfor %}
⑦ forloop.parentloop 在嵌套循环中表示父循环的forloop:
{% for country in countries %} <table> {% for city in country.city_list %} <tr> <td>Country #{{ forloop.parentloop.counter }} </td> <td>City #{{ forloop.counter }}</td> <td>{{ city }}</td> </tr> {% endfor %} </table> {% endfor %}
3、继承
①模板继承允许你建立一个基本的”骨架”模板, 它包含你所有最常用的站点元素 并 定义了一些可以被子模板覆盖的block。
注:一个html页面只能继承一个父模板,不能继承多个
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>{% block title %}{% endblock %}</title> <style> .body-header{ background-color: black; } </style> </head> <body>
{# 指定继承的模板 #} {% extends 'master.html' %} {# 指定替换的位置 #} {% block title %} tp1 {% endblock %} {# 指定替换的位置 #} {% block content %} <p>tp1</p> {% endblock %}
②模板导入定制的组件include
<form> <input type="text" name="user"/> <input type="submit" value="提交"/> </form>
{# 指定继承的模板 #} {% extends 'master.html' %} {# 指定替换的位置 #} {% block title %} tp1 {% endblock %} {# 指定替换的位置 #} {% block content %} <p>tp1</p> {# 导入单独组件 #} {% include 'tag.html' %} {% endblock %}
4、Simplelistfilter
有时候我们需要在html上对后台渲染的页面进行二次处理,比如把字符串的首字母大写、字符进行计算操作等。
(1)django默认自带方法
{{ item.event_start|date:"Y-m-d H:i:s"}} #日期格式进行转换 {{ bio|truncatewords:"30" }} #取字符串前30位 {{ my_list|first|upper }} #第一个字符大写 {{ name|lower }} #所有字符小写
(2)自定义simple_tag、filter
① 在app中创建templatetags文件夹
② templatetags中创建任意 .py 文件,如:handle.py
from django import template from django.utils.safestring import mark_safe register = template.Library() @register.simple_tag() def sub(a1,a2): #能添加多个参数 return a1 + a2 @register.filter() def lzl(a1,a2): #只能传入两个参数 return a1 + a2
③ 在settings中配置当前app,不然django无法找到自定义的simple_tag
INSTALLED_APPS = ( ...... 'cmdb', )
④ 导入和使用simple_tag、filter
{# 导入py文件名 #} {% load handle %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div>{{ name|lower }}</div> <div>{{ name|upper }}</div> {% sub 1 2 %} {{ 'hello'|lzl:'world'}} </body> </html> {#页面内容#} {#3 helloworld#}
(3)django数据库choice获取字段
device_status_choices = ( (1, '上架'), (2, '在线'), (3, '离线'), (4, '下架'), ) device_type_id = models.IntegerField('设备类型',choices=device_type_choices, default=1) <td colspan="4">{{ response.data.asset.get_device_status_id_display }}</td>
二、分页
1、简单分页
涉及xss攻击,需要用到mark_safe方法,使用此方法字符串传输到后端后,已html形式显示,而非字符串
分页数进行定制,添加上一页、下一页,增加跳转功能,实现分页的完整功能
① 设定每页显示数据条数
② 用户输入页码(第一页、第二页...)
③ 设定显示多少页号
④ 获取当前数据总条数
⑤ 根据设定显示多少页号和数据总条数计算出,总页数
⑥ 根据设定的每页显示条数和当前页码,计算出需要取数据表的起始位置
⑦ 在数据表中根据起始位置取值,页面上输出数据
⑧ 输出分页html,如:[上一页][1][2][3][4][5][下一页]
from app01 import views urlpatterns = [ ..... url(r'^user_list/', views.user_list), ]
LIST = [] for i in range(109): LIST.append(i) from django.utils.safestring import mark_safe # def user_list(request): current_page = request.GET.get('p',1) # 通过输入p页,利用get方法获取当前页码。不输入默认为第1页。得到的是一个字符串。 current_page = int(current_page) # 把字符串 --> 数字 start = (current_page-1)*10 # 起始页 end = current_page*10 # 结束页 data = LIST[start:end] # 起始页--结束页的所有数据 all_count = len(LIST) # 总数据个数 total_count,y = divmod(all_count,10) # 总页面数,每页多少条数据;divmod():整除,余数 if y : # 存在余数,总页面数+1 total_count +=1 pager_num = 11 # (显示的)页码数 page_list = [] # if total_count < pager_num : # ①总页面数 <(显示的)页码数 start_index = 1 end_index = total_count + 1 else: # ②总页面数 >=(显示的)页码数 if current_page <= pager_num/2: #【开头】 start_index = 1 # 首页 end_index = pager_num + 1 elif current_page + (pager_num-1)/2 >= total_count: #【中间】 start_index = total_count - (pager_num-1) end_index = total_count + 1 else: #【结尾】 start_index = current_page - (pager_num-1)/2 end_index = current_page + (pager_num-1)/2 + 1 #最后一页 # 上下页码 if current_page == 1: prev = '<a class="page" href="javascript:void(0)">上一页</a>' # 什么都不干 else: prev = '<a class="page" href="/user_list/?p=%s">上一页</a>'%(current_page-1) page_list.append(prev) for i in range(int(start_index),int(end_index)): #循环所有页码,选中的页码(当前页)改变样式,没选中的不改变样式 if i == current_page: temp = '<a class="page active" href="/user_list/?p=%s">%s</a>'%(i,i) else: temp = '<a class="page" href="/user_list/?p=%s">%s</a>'%(i,i) page_list.append(temp) if current_page == total_count: nex = '<a class="page" href="javascript:void(0)">下一页</a>' # 什么都不干 else: nex = '<a class="page" href="/user_list/?p=%s">下一页</a>'%(current_page+1) page_list.append(nex) # 跳转 可以写到前端 jump = ''' <input type="text" /><a onclick="jumpTo(this,'/user_list/?p=');">GO</a> <script> function jumpTo(ths,base) { var val = ths.previousSibling.value; location.href = base + val; } </script> ''' page_list.append(jump) page_str = mark_safe(''.join(page_list)) # mark_safe(防止XSS攻击,否侧page_str传到前端显示的是字符串,而不是html语言) # 另一种方式在前端做 # {{ page_str|safe }} #(''.join(page_list)):将所有的页码以空字符串进行拼接 return render(request,'user_list.html',{'li':data,'page_str':page_str})
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .pagination .page{ display: inline-block; padding: 5px; background-color: cyan; margin: 5px; } .pagination .page.active{ background-color: brown; color: white; } </style> </head> <body> <ul> {% for item in li %} <li>{{ item }}</li> {% endfor %} </ul> <div class="pagination"> {{ page_str }} </div> </body> </html>
改进:页码代码跟业务代码分开,创建class类调用,最好单独创建目录分开
from app01 import views urlpatterns = [ ..... url(r'^user_list/', views.user_list), ]
LIST = [] for i in range(199): LIST.append(i) class Page: def __init__(self, current_page, data_count, per_page_count=10, pager_num=7): self.current_page = current_page self.data_count = data_count self.per_page_count = per_page_count self.pager_num = pager_num @property # 利用属性方法:把方法变成静态属性 def start(self): return (self.current_page - 1) * self.per_page_count @property def end(self): return self.current_page * self.per_page_count @property def total_count(self): v, y = divmod(self.data_count, self.per_page_count) if y: v += 1 return v def page_str(self, base_url): page_list = [] if self.total_count < self.pager_num: #self调用方法是不用加 () start_index = 1 end_index = self.total_count + 1 else: if self.current_page <= (self.pager_num + 1) / 2: start_index = 1 end_index = self.pager_num + 1 else: start_index = self.current_page - (self.pager_num - 1) / 2 end_index = self.current_page + (self.pager_num + 1) / 2 if (self.current_page + (self.pager_num - 1) / 2) > self.total_count: end_index = self.total_count + 1 start_index = self.total_count - self.pager_num + 1 if self.current_page == 1: prev = '<a class="page" href="javascript:void(0);">上一页</a>' else: prev = '<a class="page" href="%s?p=%s">上一页</a>' % (base_url, self.current_page - 1,) page_list.append(prev) for i in range(int(start_index), int(end_index)): if i == self.current_page: temp = '<a class="page active" href="%s?p=%s">%s</a>' % (base_url, i, i) else: temp = '<a class="page" href="%s?p=%s">%s</a>' % (base_url, i, i) page_list.append(temp) if self.current_page == self.total_count: nex = '<a class="page" href="javascript:void(0);">下一页</a>' else: nex = '<a class="page" href="%s?p=%s">下一页</a>' % (base_url, self.current_page + 1,) page_list.append(nex) jump = """ <input type='text' /><a onclick='jumpTo(this, "%s?p=");'>GO</a> <script> function jumpTo(ths,base){ var val = ths.previousSibling.value; location.href = base + val; } </script> """ % (base_url,) page_list.append(jump) page_str = mark_safe("".join(page_list)) return page_str
from django.utils.safestring import mark_safe def user_list(request): current_page = request.GET.get('p', 1) current_page = int(current_page) page_obj = Page(current_page,len(LIST)) data = LIST[page_obj.start:page_obj.end] page_str = page_obj.page_str("/user_list/") return render(request, 'user_list.html', {'li': data,'page_str': page_str})
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .pagination .page{ display: inline-block; padding: 5px; background-color: cyan; margin: 5px; } .pagination .page.active{ background-color: brown; color: white; } </style> </head> <body> <ul> {% for item in li %} <li>{{ item }}</li> {% endfor %} </ul> <div class="pagination"> {{ page_str }} </div> </body> </html>
三、Cookie
1、概述
Cookie,有时也用其复数形式 Cookies,指某些网站为了辨别用户身份、进行 session 跟踪而储存在用户本地终端上的数据(通常经过加密)。(可以叫做浏览器缓存:Cookie就是一段字符串,保存于本机电脑上。)
① 获取Cookie
request.COOKIES['key'] request.COOKIES.get('key') request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None) 参数: default: 默认值 salt: 加密盐 max_age: 后台控制过期时间
② 设置Cookie
rep = HttpResponse(...) 或 rep = render(request, ...) #return的对象 rep.set_cookie(key,value,...) rep.set_signed_cookie(key,value,salt='加密盐',...) 参数: key, 键 value='', 值 max_age=None, 超时时间 单位秒 expires=None, 超时时间(IE requires expires, so set it if hasn't been already.) 单位日期 path='/', Cookie生效的路径,/ 表示根路径,特殊的:跟路径的cookie可以被任何url的页面访问 指定生效路径 domain=None, Cookie生效的域名 secure=False, https传输改为True httponly=False 只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖) 补充: # max_age 10秒失效 result.set_cookie('username',u,max_age=10) # expires 设置失效日期 import datetime current_date = datetime.datetime.utcnow() # utcnow()当前时间 current_date = current_date + datetime.timedelta(seconds=5) # timedelta时间差 result.set_cookie('username',u,expires=current_date) # 加密(带签名的) obj = HttpResponse('s') obj.set_signed_cookie('username',"kangbazi",salt="asdfasdf") #加密 request.get_signed_cookie('username',salt="asdfasdf") # 解密 注:由于cookie保存在客户端的电脑上,所以,JavaScript和jquery也可以操作cookie <script src='/static/js/jquery.cookie.js'></script> $.cookie("list_pager_num", 30,{ path: '/' }); #key vaule 字典
2、用户登录
利用cookie做用户登录页面,只有登录成功才能进入到后台管理
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <h1>欢迎登录:{{ current_user }}</h1> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <form action="/login/" method="POST"> <input type="text" name="username" placeholder="用户名" /> <input type="password" name="pwd" placeholder="密码" /> <input type="submit" /> </form> </body> </html>
user_info = { 'solo':{'pwd':'123456'} } def login(request): if request.method == 'GET': return render(request,'login.html') if request.method == 'POST': u = request.POST.get('username') p = request.POST.get('pwd') dic = user_info.get(u) if not dic: return render(request,'login.html') if dic['pwd']== p: result = redirect('/index/') result.set_cookie('username',u) #设置cookie值 return result else: return render(request, 'login.html') def index(request): v = request.COOKIES.get('username') #获取cookie值 if not v : return redirect('/login/') return render(request,'index.html',{'current_user':v})
3、定制分页
根据用户选择的数字,显示页面的数量
<body> <ul> {% for item in li %} <li>{{ item }}</li> {% endfor %} </ul> <div> <select id='pg' onchange="ChangePageSize(this)"> #给选中的页面增加一个事件 <option value="10">10</option> <option value="30">30</option> <option value="50">100</option> </select> </div> <div class="pagination"> {{ page_str }} </div> <script src="/static/jquery-1.12.4.js"></script> <script src="/static/jquery.cookie.js"></script> #注意顺序 <script> $(function () { # 页面加载完成后执行此方法 var v = $.cookie('per_page_count',{'path':'/user_list/'});#获取选中的值,设置为新一页的默认值;路径:只有当前页面受影响 $('#pg').val(v); }); function ChangePageSize(ths) { var v = $(ths).val(); # 获取用户当前选择的值 $.cookie('per_page_count',v,{'path':'/user_list/'}); location.reload() } </script> </body>
from django.utils.safestring import mark_safe def user_list(request): current_page = request.GET.get('p', 1) current_page = int(current_page) per_page_count = request.COOKIES.get('per_page_count',10) #获取cookie值 per_page_count = int(per_page_count) page_obj = Page(current_page,len(LIST),per_page_count) data = LIST[page_obj.start:page_obj.end] page_str = page_obj.page_str("/user_list/") return render(request, 'user_list.html', {'li': data,'page_str': page_str})
4、登录认证(装饰器)
①FBV
def auth(func): def inner(request,*args,**kwargs): v = request.COOKIES.get('username') # 获取cookie值 if not v: return redirect('/login/') return func(request,*args,**kwargs) return inner @auth #认证装饰 def index(request): v = request.COOKIES.get('username') return render(request, 'index.html', {'current_user': v})
②CBV
def auth(func): def inner(request,*args,**kwargs): v = request.COOKIES.get('username') # 获取cookie值 if not v: return redirect('/login/') return func(request,*args,**kwargs) return inner from django import views from django.utils.decorators import method_decorator @method_decorator(auth,name='dispatch') #第一种方式 class Order(views.View): # @method_decorator(auth) #第二种方式 # def dispatch(self, request, *args, **kwargs): # return super(Order,self).dispatch(request, *args, **kwargs) # @method_decorator(auth) #单独添加 def get(self,reqeust): v = reqeust.COOKIES.get('username111') return render(reqeust,'index.html',{'current_user': v}) def post(self,reqeust): v = reqeust.COOKIES.get('username111') return render(reqeust,'index.html',{'current_user': v})
三、Session
1、概述
两者区别:Cookie是保存在用户浏览器端的键值对,Session是保存在服务器端的键值对;Cookie做用户验证的时,敏感信息不适合放在Cookie中,别人可以分析存放在本地的Cookie并进行Cookie欺骗,考虑到安全应当使用Session;用户验证时两者要结合使用,Session可保存到文件,内存,数据库任意地方。 (session 保存于服务器,用来保存用户的会话信息,依赖于Cookies)
① 获取
# 获取Session中数据 request.session['k1'] request.session.get('k1', None)
② 生成
# 生成Session中数据 request.session['k1'] = 123 request.session.setdefault('k1', 123) # 存在则不设置
③ 删除
# 删除Session中某条数据 del request.session['k1'] # 删除当前用户的所有Session数据 request.session.delete("session_key") request.session.clear() #注销时可用
④ 键值对
# 所有 键、值、键值对 request.session.keys() request.session.values() request.session.items() request.session.iterkeys() request.session.itervalues() request.session.iteritems()
⑤ 超时时间
# 设置超时时间 request.session.set_expiry(value) #默认超时时间为两周 *如果value是个整数,session会在些秒数后失效。 *如果value是个datatime或timedelta,session就会在这个时间后失效。 *如果value是0, 用户关闭浏览器session就会失效。 *如果value是None, session会依赖全局session失效策略。
⑥ 其他
# 用户session的随机字符串 request.session.session_key # 将所有Session失效日期小于当前日期的数据删除 request.session.clear_expired() # 检查 用户session的随机字符串 在数据库中是否 一般用不到 request.session.exists("session_key")
2、用户登录
利用Session做用户登录页面,只有登录成功才能进入到后台管理
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/login/" method="post"> <input type="text" name="user" /> <input type="text" name="pwd" /> <input type="checkbox" name="session" value="1"/> 保存1个月 <input type="submit" value="提交" /> </form> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {{ request.session.username }} </body> </html>
def login(request):
if request.method == 'GET':
return render(request,'login.html')
elif request.method == 'POST':
user = request.POST.get('user')
pwd = request.POST.get('pwd')
if user == 'root' and pwd == "123":
# 生成随机字符串
# 写到用户浏览器Cookie
# 保存到Session中
# 在随机字符串对应的字典中设置相关内容...
request.session['username'] = user
request.session['if_login'] = True #可不加 直接判断username也可以
if request.POST.get('session') == '1': #单独设置超时时间,当前session生效,不影响全局
request.session.set_expiry(10) #10秒
return redirect('/index/')
else:
return redirect('/login/')
def index(request):
# 获取当前用户的随机字符串
# 根据随机字符串获取对应信息
if request.session.get('if_login'):
return render(request, 'index.html')
else:
return redirect('/login/')
3、Django中默认支持Session,其内部提供了5种类型的Session供开发者使用:
①数据库Session(默认)
Django默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session 表中。 a. 配置 settings.py SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默认) SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认) SESSION_COOKIE_PATH = "/" # Session的cookie保存的路径(默认) SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名(默认) SESSION_COOKIE_SECURE = False # 是否Https传输cookie(默认) SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http传输(默认) SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周)(默认) SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否关闭浏览器使得Session过期(默认) SESSION_SAVE_EVERY_REQUEST = False # 是否每次请求都保存Session,默认修改之后才保存(默认) b. 使用 def index(request): # 获取、设置、删除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的随机字符串 request.session.session_key # 将所有Session失效日期小于当前日期的数据删除 request.session.clear_expired() # 检查 用户session的随机字符串 在数据库中是否 request.session.exists("session_key") # 删除当前用户的所有Session数据 request.session.delete("session_key") request.session.set_expiry(value) * 如果value是个整数,session会在些秒数后失效。 * 如果value是个datatime或timedelta,session就会在这个时间后失效。 * 如果value是0,用户关闭浏览器session就会失效。 * 如果value是None,session会依赖全局session失效策略。
②缓存存储Session
可以设置为Memcache缓存,默认不支持redis(可以使用网上插件)
#本地内存存储session 配置settings.py SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 引擎 SESSION_CACHE_ALIAS = 'default' # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置 SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串 SESSION_COOKIE_PATH = "/" # Session的cookie保存的路径 SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名 SESSION_COOKIE_SECURE = False # 是否Https传输cookie SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http传输 SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周) SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否关闭浏览器使得Session过期 SESSION_SAVE_EVERY_REQUEST = False # 是否每次请求都保存Session,默认修改之后才保存 #Memcache缓存 配置settings.py SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 引擎 SESSION_CACHE_ALIAS = 'db' # 使用的缓存别名,此处别名依赖缓存的设置 CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION': [ '172.19.26.240:11211', '172.19.26.242:11211', ] }, 'db': { 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION': [ '172.19.26.240:11211', '172.19.26.242:11211', ] } }
③文件存储Session
#文件session 配置 settings.py SESSION_ENGINE = 'django.contrib.sessions.backends.file' # 引擎 SESSION_FILE_PATH = None # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir() # 如:/var/folders/d3/j9tj0gz93dg06bmwxmhh6_xm0000gn/T SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串 SESSION_COOKIE_PATH = "/" # Session的cookie保存的路径 SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名 SESSION_COOKIE_SECURE = False # 是否Https传输cookie SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http传输 SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周) SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否关闭浏览器使得Session过期 SESSION_SAVE_EVERY_REQUEST = False # 是否每次请求都保存Session,默认修改之后才保存
④缓存+数据库Session
#缓存+数据库Session 数据库用于做持久化,缓存用于提高效率,先去缓存中取数据,缓存没有再去数据库中取,然后在缓存中存一份 配置settings.py SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' # 引擎
⑤加密cookie Session
#加密cookie Session 数据都存在于客户端 配置settings.py SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies' # 引擎 #注:当使用Session时,需要执行makemigrations和 migrate,数据库上会自动生成django_session数据表
Session&Cookie 总结
Cookie就是一段字符串,保存于本机电脑上。
session 保存于服务器,用来保存用户的会话信息,依赖于Cookies
流程:举个例子,咱们在登录一个网站后,拿JD举例,如果我登录进去之后,在想点击订单的时候。server断怎么判断我是“我”,而不是其他人呢?
Http是短连接,那么Server端肯定有一个保存我登录状态的地方(session),那server怎么判断是我发送过来的请求呢?就是通过Cookie!
当客户端访问过来后,server端会在IE里生成一个Cookie,当访问过来的时候就可以通过Cookie进行判断
在session中,我们可以设置多个key:value的值,我们可以在session设置,当用户登录的时候,我们把的用户名,增加到session中,那么用户携带cookie访问的时候,我们就能判断是哪个一用来访问的!
Session和Cookie好处:Cookie可以理解为一个身份证ID,你只能拿着他去和Server端进行通信,如果你没有这个ID那么server端也不知道你是谁!(我在写博客的时候在做Cookie和Session的实验,把Cookie删掉了!当我保存的时候直接给我提出来了,为什么呢?就是因为,server端不知道我是谁了,我已经没有密钥了。)
所以,只要Session和Cookie任意一方失效,就可以理解为:Cookie失效就相当于身份证ID过期,需要重新认证才可以继续使用。Session失效就相当于银行里的数据标识此ID无效,也需要重新申请。