django的session使用,
甜饼干
Cookie的由来大家都知道HTTP协议是无状态的。
无状态意味着每个请求都是独立的,它的执行和结果与前面和后面的请求没有直接关系。它不会直接受到前一个请求的响应或后一个请求的响应的影响。
用一个有趣的词来形容,人生就像第一眼。对于服务器来说,每一个请求都是全新的。
状态可以理解为客户端和服务器在某个会话中产生的数据,也就是说不会保留无状态的数据。会话中生成的数据就是我们需要保存的,也就是说“保持状态”。因此,Cookie就是在这样的场景下诞生的。
什么是CookieCookie特指一小段信息。它是由服务器发送并存储在浏览器中的一组键值对。下次访问服务器时,浏览器会自动携带这些键值对,以便服务器提取有用的信息。
Cookie的工作原理是:内容由服务器生成,浏览器收到请求后保存在本地;当浏览器再次访问时,浏览器会自动带来Cookie,让服务器通过Cookie的内容判断这是谁。
检查Cookie我们使用Chrome浏览器,打开开发者工具。
姜戈的曲奇行动。cookie[ key ]
request.get _ signed _ cookie的参数(key,default=raise _ error,salt= ,max _ age=none):
Default:默认值salt:加密salt max_age:后台控制过期时间设置Cookierep=HttpResponse(.)
rep=render(请求,)
rep.set_cookie(键,值,)
Rep.set _ signed _ cookie (key,value,salt= encryption salt ,)参数:
Key,key value=“”,value max_age=None,timeout expires=None,timeout (ie要求expires,所以如果还没有设置,就设置它。)path=/,cookie生效的路径,/表示根路径,特殊:根路径中的cookie可以被任何url访问。Domain=none,cookie生效的域名为secure=false,httpS传输为httponly=False,只能通过HTTP协议传输,JavaScript无法获取(非绝对,底层捕获可以获取或覆盖)。删除Cookiedef注销(请求):
rep=redirect(/login/)
Rep.delete_cookie(user) #删除用户浏览器上先前设置的usercookie值
返回repCookie版本登录验证
def check_login(函数):
@wraps(func)
def inner(request,*args,*kwargs):
next_url=request.get_full_path()
if request . get _ signed _ cookie( log in ,salt=SSS ,default=None)= yes :
已经登录的用户数量.
return func(request,*args,**kwargs)
否则:
#未登录的用户只需跳转到登录页面。
返回重定向(/login/?next={} 。格式(下一个url))
返回内部
定义登录(请求):
if request.method==POST :
用户名=请求。POST.get(用户名)
passwd=请求POST.get(密码)
如果username==xxx 和passwd==dashabi :
next_url=请求。GET.get(下一个)
如果next_url和next_url!=/logout/:
响应=重定向(下一个url)
否则:
response=redirect(/class _ list/)
response . set _ signed _ cookie( log in , yes ,salt=SSS )
返回响应
呈现(请求, login.html) cookie版本登录
Session Cookie的起源在一定程度上解决了“保持状态”的需要,但是由于Cookie本身最大支持4096字节,而且Cookie本身存储在客户端,可能会被截获或窃取,所以需要一种新的东西,可以支持更多的字节,它存储在服务器端,安全性高。这是会议。
问题来了。基于HTTP协议的无状态特性,服务器根本不知道访问者是谁。那么上面的Cookie就起到了桥梁的作用。
我们可以为每个客户端的Cookie分配一个唯一的id,这样当用户访问时,服务器将知道是谁通过Cookie访问的。然后根据不同Cookie的id,在服务器上保存一段时间的一些私密信息,比如“账号密码”等等。
总结而言:Cookie弥补了超文本传送协议无状态的不足,让服务器知道来的人是"谁";但是饼干以文本的形式保存在本地,自身安全性较差;所以我们就通过饼干识别不同的用户,对应的在会议里保存私密的信息以及超过4096字节的文本。
另外,上述所说的饼干和会议其实是共通性的东西,不限于语言和框架。
姜戈中会议相关方法
# 获取、设置、删除会议中数据
request.session[k1]
request.session.get(k1 ,无)
request.session[k1]=123
request.session.setdefault(k1 ,123) #存在则不设置
del request.session[k1]
# 所有键、值、键值对
请求。会话。钥匙()
request.session.values()
request.session.items()
request.session.iterkeys()
request.session.itervalues()
request.session.iteritems()
# 会话会议的键
请求。会话。会话_密钥
# 将所有会议失效日期小于当前日期的数据删除
request.session.clear_expired()
# 检查会话会议的键在数据库中是否存在
request.session.exists(会话密钥)
# 删除当前会话的所有会议数据
request.session.delete()
# 删除当前的会话数据并删除会话的饼干。
request.session.flush()
这用于确保前面的会话数据不可以再次被用户的浏览器访问
例如,django.contrib.auth.logout()函数中就会调用它。
# 设置会话会议和饼干的超时时间
请求.会话.设置_到期(值)
* 如果价值是个整数,会话会在些秒数后失效。
* 如果价值是个数据时间或时间增量,会话就会在这个时间后失效。
* 如果价值是0,用户关闭浏览器会议就会失效。
* 如果价值是无,会话会依赖全局会议失效策略。
会议流程解析
会议版登陆验证
从函数工具导入包装
定义检查_登录(函数):
@wraps(func)
def inner(request,*args,*kwargs):
next_url=request.get_full_path()
if request.session.get(user ):
return func(request,*args,**kwargs)
否则:
返回重定向(/login/?next={} .格式(下一个网址))
返回内部
定义登录(请求):
if request.method==POST :
用户=请求. POST.get(用户)
pwd=请求POST.get(pwd )
如果用户==亚历克斯和pwd==alex1234 :
# 设置会议
request.session[用户]=用户
# 获取跳到登陆页面之前的统一资源定位器
next_url=请求. GET.get(下一个)
# 如果有,就跳转回登陆之前的统一资源定位器
if next_url:
返回重定向(下一个网址)
# 否则默认跳转到指数页面
否则:
返回重定向(/index/)
返回渲染(请求,《login.html》)
@检查_登录
定义注销(请求):
# 删除所有当前请求相关的会议
request.session.delete()
返回重定向(/login/)
@检查_登录
定义索引(请求):
当前用户=请求。会话。get(用户,无)
返回呈现(请求、 index.html 、{ 用户:当前用户})会话版登录验证
姜戈中的会议配置姜戈中默认支持会话,其内部提供了5种类型的会议供开发者使用。
1.数据库会议
SESSION _ ENGINE= django。贡献。会话。后端。db #引擎(默认)
2.缓存会议
SESSION _ ENGINE= django。贡献。会话。后端。缓存 #引擎
会话缓存别名=默认 #使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置
3.文件会议
SESSION _ ENGINE= django。贡献。会话。后端。文件 #引擎
会话文件路径=无#缓存文件路径,如果为没有,则使用临时文件模块获取一个临时地址tempfile.gettempdir()
4.缓存数据库
SESSION _ ENGINE= django。贡献。会话。后端。cached _ db #引擎
5.加密饼干会话
SESSION _ ENGINE= django。贡献。会话。后端。签名的cookies #引擎
其他公用设置项:
会话饼干名称=会话id #会话的甜饼干保存在浏览器上时的钥匙,即:会话id=随机字符串(默认)
SESSION _ COOKIE _ PATH=/ # SESSION的甜饼干保存的路径(默认)
会话_ COOKIE _域=无#会话的甜饼干保存的域名(默认)
SESSION_COOKIE_SECURE=False #是否安全超文本传输协议传输cookie(默认)
SESSION_COOKIE_HTTPONLY=True #是否会议的甜饼干只支持超文本传送协议(超文本传输协议的缩写)传输(默认)
SESSION _ COOKIE _ AGE=1209600 # SESSION的甜饼干失效日期(2周)(默认)
SESSION _ EXPIRE _ AT _ BROWSER _ CLOSE=False #是否关闭浏览器使得会议过期(默认)
SESSION _ SAVE _ EVERY _ REQUEST=False #是否每次请求都保存会话,默认修改之后才保存(默认)姜戈中会议相关设置
血容量中加装饰器相关血容量实现的登录视图
类登录视图(视图):
定义获取(自身,请求):
处理得到请求
返回渲染(请求,《login.html》)
定义发布(自己,请求):
处理邮政请求
用户=请求. POST.get(用户)
pwd=请求POST.get(pwd )
如果用户==亚历克斯和pwd==alex1234 :
next_url=请求. GET.get(下一个)
# 生成随机字符串
# 写浏览器甜饼干会话id:随机字符串
# 写到服务端会话:
# {
# 随机字符串:{ 用户:亚历克斯 }
# }
request.session[用户]=用户
if next_url:
返回重定向(下一个网址)
否则:
返回重定向(/index/)
返回渲染(请求,《login.html》)
要在血容量视图中使用我们上面的检查_登录装饰器,有以下三种方式:
从姜戈。utils。装饰者导入方法_装饰者
1.加在血容量视图的得到或邮政方法上
从姜戈。utils。装饰者导入方法_装饰者
班级主页视图(视图):
定义调度(自身,请求,*参数,*kwargs):
返回超级(HomeView,self).派遣(请求,*参数,*克沃格)
定义获取(自身,请求):
返回渲染(请求,《home.html》)
@method_decorator(检查_登录)
定义发布(自己,请求):
打印(主页视图发布方法.)
返回重定向(/index/)
2.加在派遣方法上
从姜戈。utils。装饰者导入方法_装饰者
班级主页视图(视图):
@method_decorator(检查_登录)
定义调度(自身,请求,*参数,*kwargs):
返回超级(HomeView,self).派遣(请求,*参数,*克沃格)
定义获取(自身,请求):
返回渲染(请求,《home.html》)
定义发布(自己,请求):
打印(主页视图发布方法.)
返回重定向(/index/)
因为血容量中首先执行的就是派遣方法,所以这么写相当于给得到和邮政方法都加上了登录校验。
3.直接加在视图类上,但方法_装饰者必须传名字关键字参数
如果得到方法和邮政方法都需要登录校验的话就写两个装饰器。
从姜戈。utils。装饰者导入方法_装饰者
@method_decorator(check_login,name=get )
@method_decorator(check_login,name=post )
班级主页视图(视图):
定义调度(自身,请求,*参数,*kwargs):
返回超级(HomeView,self).派遣(请求,*参数,*克沃格)
定义获取(自身,请求):
返回渲染(请求,《home.html》)
定义发布(自己,请求):
打印(主页视图发布方法.)
返回重定向(/index/)
补充跨站点请求伪造代币相关装饰器在血容量只能加到派遣方法上
备注:
csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便设置中没有设置全局中间件csrf_exempt,取消当前函数防跨站请求伪造功能,即便设置中设置了全局中间件。
从django.views.decorators.csrf导入csrf_exempt,csrf_protect
班级主页视图(视图):
@method_decorator(csrf_exempt)
定义调度(自身,请求,*参数,*kwargs):
返回超级(HomeView,self).派遣(请求,*参数,*克沃格)
定义获取(自身,请求):
返回渲染(请求,《home.html》)
定义发布(自己,请求):
打印(主页视图发布方法.)
返回重定向(/index/)
分页自定义分页
数据=[]
对于范围内的一(1302):
tmp={id: i, name: alex-{} .格式(一)}
数据追加(tmp)
打印(数据)
定义用户列表(请求):
# user_list=data[0:10]
# user_list=data[10:20]
尝试:
current_page=int(请求. GET.get(page ))
例外情况为e:
current_page=1
per_page=10
# 数据总条数
总计数=长度(数据)
# 总页码
total_page,more=divmod(总计数,每页)
如果更多:
total_page=1
# 页面最多显示多少个页码
max_show=11
half_show=int((max_show-1)/2)
如果当前页面=一半显示:
show_start=1
显示结束=最大显示
否则:
如果current _ page half _ show=total _ page:
显示开始=总页数-最大显示
显示结束=总页数
否则:
show_start=当前页面-半页显示
show_end=当前页面半页显示
# 数据库中获取数据
data_start=(当前页- 1) *每页
数据_结束=当前页*每页
用户列表=数据[数据开始:数据结束]
# 生成页面上显示的页码
page_html_list=[]
# 加首页
first_li=阿利href=/user_list/?page=1 首页/a /li
page_html_list.append(first_li)
# 加上一页
如果当前页面==1:
prev_li=阿利href=# 上一页/a /li
否则:
prev_li=阿利href=/user_list/?page={} 上一页/a/李.格式(当前页面- 1)
page_html_list.append(prev_li)
对于范围内的我(显示开始,显示结束1):
如果i==当前页面:
li_tag=阿利href=/user_list/?page={ 0 }"{ 0 }/a/Li .格式(一)
否则:
li_tag=阿利href=/user_list/?page={ 0 }"{ 0 }/a/Li .格式(一)
page_html_list.append(li_tag)
# 加下一页
如果当前页面==总页面:
next_li=阿利href=# 下一页/a /li
否则:
next_li=阿利href=/user_list/?page={} 下一页/a/李.格式(当前_第一页)
page_html_list.append(next_li)
# 加尾页
page_end_li=阿利href=/user_list/?page={} 尾页/a/李.格式(总页数)
page _ html _ list。追加(page _ end _ Li)
page_html=" " .join(page_html_list)
返回渲染(请求、 user_list.html 、{user_list: user_list, page_html: page_html})稳扎稳打版
类分页(对象):
def __init__(self,current_page,total_count,base_url,per_page=10,max_show=11):
:param current_page:当前页
:参数总计数:数据库中数据总数
:每页参数:每页显示多少条数据
:param max_show:最多显示多少页
尝试:
当前页面=int(当前页面)
例外情况为e:
current_page=1
self.current_page=当前页面
self.total_count=总计_计数
self.base_url=base_url
self.per_page=per_page
self.max_show=max_show
# 总页码
total_page,more=divmod(总计数,每页)
如果更多:
total_page=1
half_show=int((max_show - 1)/2)
self.half_show=half_show
self.total_page=total_page
@属性
定义开始(自身):
回归(自我。current _ page-1)* self。每页
@属性
定义结束(自身):
回归自我。当前_页面*自身。每页
def page_html(自身):
如果自我。current _ page=自我。半_秀:
show_start=1
show_end=self.max_show
否则:
如果自我。当前_页面自我。half _ show=自我。total _ page:
show _ start=self。total _ page-selfmax _ show
show_end=self.total_page
否则:
show _ start=self。当前_页面-自己。半秀
show _ end=自我。当前_页面自我。半秀
# 生成页面上显示的页码
page_html_list=[]
# 加首页
first_li=阿利href={}?page=1 首页/a/李.格式(self.base_url)
page_html_list.append(first_li)
# 加上一页
如果self.current_page==1:
prev_li=阿利href=# 上一页/a /li
否则:
prev_li=阿利href=“{ 0 }?page={1} 上一页/a/李.格式(self.base_url,self.current_page - 1)
page_html_list.append(prev_li)
对于范围内的我(显示开始,显示结束1):
如果i==self.current_page:
li_tag=阿利href=“{ 0 }?page={ 1 }"{ 1 }/a/Li .格式(self.base_url,I)
否则:
li_tag=阿利href=“{ 0 }?page={ 1 }"{ 1 }/a/Li .格式(self.base_url,I)
page_html_list.append(li_tag)
# 加下一页
如果自我。current _ page==自身。total _ page:
next_li=阿利href=# 下一页/a /li
否则:
next_li=阿利href=“{ 0 }?page={1} 下一页/a/李.格式(self.base_url,self.current_page 1)
page_html_list.append(next_li)
# 加尾页
page_end_li=阿利href=“{ 0 }?page={1} 尾页/a/李.格式(self.base_url,self.total_page)
page _ html _ list。追加(page _ end _ Li)
返回""。join(page_html_list)封装保存版
定义用户列表(请求):
pager=分页(请求. GET.get(page ),len(data),request.path_info)
user _ list=data[pager。开始:寻呼机。结束]
page_html=pager.page_html()
返回渲染(请求、 user_list.html 、{user_list: user_list, page_html: page_html})封装保存版使用指南
姜戈内置分页
从django .捷径导入渲染
从django.core.paginator导入分页器、EmptyPage、PageNotAnInteger
L=[]
对于范围内的一(999):
附加(一)
定义索引(请求):
当前页面=请求GET.get(p )
paginator=Paginator(L,10)
#每页:每页显示条目数量
#计数:数据总个数
#页数:总页数
#页面范围:总页数的索引范围,如: (1,10),(1,200)
#页面:第页对象
尝试:
posts=分页器。页面(当前页面)
# has_next是否有下一页
#下一页页码下一页页码
#有_上一个是否有上一页
#上一页页码上一页页码
#对象列表分页之后的数据列表
#编号当前页
#分页器分页器对象
除了PageNotAnInteger:
posts=paginator.page(1)
除了EmptyPage:
posts=分页器。页面(分页器。数量_页数)
return render(请求, index.html ,{ 帖子:帖子})内置分页视角部分
!声明文档类型
超文本标记语言
头部语言
meta charset=UTF-8
标题/标题
/头
身体
保险商实验所
{%对于帖子中的项目%}
李{ { item } }/李
{% endfor %}
/ul
差异
跨度
{% if posts.has_previous %}
a href=?p={ {帖子。上一页页码} } 上一个/a
{% endif %}
跨度
第{ { posts.number } }页,共{{ posts.paginator.num_pages }}页。
/span
{% if posts.has_next %}
a href=?p={{ posts.next_page_number }} 下一个/a
{% endif %}
/span
/div
/body
/html内置分页超文本标记语言部分
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。