python之路_django分页及session介绍
一、分页介绍
1、django 分页器
在django框架中,为我们提供了分页器Paginator,引入的方式为:from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger,其中EmptyPage为请求页码超出最大的页码抛出的异常,PageNotAnInteger为请求的页码不是一个合法的数字时抛出的异常。应用实例介绍如下:
后端函数部分:
from django.core.paginator import Paginator,EmptyPage,PageNotAnInteger
def index(request):
book_list=Book.objects.all() #取到的所有数据
paginatorObj=Paginator(book_list,5) #实例化Paginator对象,接收两个参数:所以数据,每页显示的数据条数
'''
paginator对象三个属性:
print(paginatorObj.count) 数据总条数
print(paginatorObj.num_pages) 总页码数
print(paginatorObj.page_range) 页码数的范围:range(1,paginatorObj.num_pages+1)
'''
current_num = request.GET.get("page", 1) #获取请求的页数,默认为1
current_num = int(current_num)
page_count=11 #显示的分页数
if paginatorObj.num_pages<=page_count:
pageRange=paginatorObj.page_range
else:
if current_num-5<=1:
pageRange=range(1,page_count+1)
elif current_num+5>=paginatorObj.num_pages:
pageRange = range(paginatorObj.num_pages-page_count+1, paginatorObj.num_pages + 1)
else:
pageRange = range(current_num-5, current_num+6)
try:
pageObj=paginatorObj.page(current_num)
'''
页对象的属性:
print(pageObj.has_next()) 是否有下一页,返回True或者False
print(pageObj.next_page_number()) 下一页页码数
print(pageObj.has_previous()) 是否有上一页,返回True或者False
print(pageObj.previous_page_number()) 上一页页码数
'''
except Exception: #主要解决用户输入非法页码时产生的异常
pageObj = paginatorObj.page(1)
book_list=pageObj.object_list #获取当前页对象包含的数据对象
return render(request,"index.html",locals())
html文件部分:
<body>
<div class="container">
<h4>分页器</h4>
<ul>
{% for book in book_list %}
<li>{{ book.tittle }} -----{{ book.price }}</li>
{% endfor %}
</ul>
<ul class="pagination" id="pager">
<li class="previous"><a href="/index/?page={{ 1 }}">首页</a></li>
{% if pageObj.has_previous %}
<li class="previous"><a href="/index/?page={{ pageObj.previous_page_number }}">上一页</a></li>
{% else %}
<li class="previous disabled"><a href="#">上一页</a></li>
{% endif %}
{% for num in pageRange %}
{% if num == current_num %}
<li class="item active"><a href="/index/?page={{ num }}">{{ num }}</a></li>
{% else %}
<li class="item"><a href="/index/?page={{ num }}">{{ num }}</a></li>
{% endif %}
{% endfor %}
{% if pageObj.has_next %}
<li class="next"><a href="/index/?page={{ pageObj.next_page_number }}">下一页</a></li>
{% else %}
<li class="next disabled"><a href="#">下一页</a></li>
{% endif %}
<li class="previous"><a href="/index/?page={{ paginatorObj.num_pages }}">尾页</a></li>
</ul>
</div>
</body>
2、自定义分页器
如下实例为自定义分页:
"""
分页组件使用示例:
def index(request):
obj = Pagination(request.GET.get('page',1),len(USER_LIST),request.path_info)
page_user_list = USER_LIST[obj.start:obj.end]
page_html = obj.page_html()
return render(request,'index.html',{'users':page_user_list,'page_html':page_html})
"""
class Pagination(object):
def __init__(self,current_page,all_count,base_url,per_page_num=10,pager_count=11):
"""
封装分页相关数据
:param current_page: 当前页
:param all_count: 数据库中的数据总条数
:param per_page_num: 每页显示的数据条数
:param base_url: 分页中显示的URL前缀
:param pager_count: 最多显示的页码个数
"""
try:
current_page = int(current_page)
except Exception as e:
current_page = 1
if current_page <1:
current_page = 1
self.current_page = current_page
self.all_count = all_count
self.per_page_num = per_page_num
self.base_url = base_url
# 总页码
all_pager, tmp = divmod(all_count, per_page_num)
if tmp:
all_pager += 1
self.all_pager = all_pager
self.pager_count = pager_count
self.pager_count_half = int((pager_count - 1) / 2)
@property
def start(self):
return (self.current_page - 1) * self.per_page_num
@property
def end(self):
return self.current_page * self.per_page_num
def page_html(self):
# 如果总页码 < 11个:
if self.all_pager <= self.pager_count:
pager_start = 1
pager_end = self.all_pager + 1
# 总页码 > 11
else:
# 当前页如果<=页面上最多显示11/2个页码
if self.current_page <= self.pager_count_half:
pager_start = 1
pager_end = self.pager_count + 1
# 当前页大于5
else:
# 页码翻到最后
if (self.current_page + self.pager_count_half) > self.all_pager:
pager_end = self.all_pager + 1
pager_start = self.all_pager - self.pager_count + 1
else:
pager_start = self.current_page - self.pager_count_half
pager_end = self.current_page + self.pager_count_half + 1
page_html_list = []
first_page = '<li><a href="%s?page=%s">首页</a></li>' % (self.base_url,1,)
page_html_list.append(first_page)
if self.current_page <= 1:
prev_page = '<li><a href="#">上一页</a></li>'
else:
prev_page = '<li><a href="%s?page=%s">上一页</a></li>' % (self.base_url,self.current_page - 1,)
page_html_list.append(prev_page)
for i in range(pager_start, pager_end):
if i == self.current_page:
temp = '<li class="active"><a href="%s?page=%s">%s</a></li>' % (self.base_url,i, i,)
else:
temp = '<li><a href="%s?page=%s">%s</a></li>' % (self.base_url,i, i,)
page_html_list.append(temp)
if self.current_page >= self.all_pager:
next_page = '<li><a href="#">下一页</a></li>'
else:
next_page = '<li><a href="%s?page=%s">下一页</a></li>' % (self.base_url,self.current_page + 1,)
page_html_list.append(next_page)
last_page = '<li><a href="%s?page=%s">尾页</a></li>' % (self.base_url,self.all_pager,)
page_html_list.append(last_page)
return ''.join(page_html_list)
上述类中page_html()函数返回的是分页列表中包含li标签的字符串,替换到相应html文件的中的方式如下:
函数获取字符串:

字符串转换成html:

二、session介绍
cookie不属于http协议范围,由于http协议无法保持状态,但实际情况,我们却又需要“保持状态”,因此cookie就是在这样一个场景下诞生。cookie的工作原理是:由服务器产生内容,浏览器收到请求后保存在本地;当浏览器再次访问时,浏览器会自动带上cookie,这样服务器就能通过cookie的内容来判断这个是“谁”了。cookie虽然在一定程度上解决了“保持状态”的需求,但是由于cookie本身最大支持4096字节,以及cookie本身保存在客户端,可能被拦截或窃取,因此就需要有一种新的东西,它能支持更多的字节,并且他保存在服务器,有较高的安全性。这就是session。
问题来了,基于http协议的无状态特征,服务器根本就不知道访问者是“谁”。那么上述的cookie就起到桥接的作用。我们可以给每个客户端的cookie分配一个唯一的id,这样用户在访问时,通过cookie,服务器就知道来的人是“谁”。然后我们再根据不同的cookie的id,在服务器上保存一段时间的私密资料,如“账号密码”等等。
结而言:cookie弥补了http无状态的不足,让服务器知道来的人是“谁”;但是cookie以文本的形式保存在本地,自身安全性较差;所以我们就通过cookie识别不同的用户,对应的在session里保存私密的信息以及超过4096字节的文本。
另外,上述所说的cookie和session其实是共通性的东西,不限于语言和框架
1、cookie与session比较
(a)cookie是保存在浏览器端的键值对,而session是保存的服务器端的键值对,但是依赖cookie。
(b)以登录为例,cookie为通过登录成功后,设置明文的键值对,并将键值对发送客户端存,明文信息可能存在泄漏,不安全;session则是生成随机字符串,发给用户,并写到浏览器的cookie中,同时服务器自己也会保存一份。
(c)在登录验证时,cookie:根据浏览器发送请求时附带的cookie的键值对进行判断,如果存在,则验证通过;session:在请求用户的cookie中获取随机字符串,根据随机字符串在session中获取其对应的值进行验证
原理如下:

2、session的分类
如上,根据session在服务器中的保存位置分如下5种:
(1)数据库session
顾名思义,session的数值是保存在数据库中的,Django默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session 表中。使用此类型session之前需要通过执行如下两个命令进行创建session需要的表。如下:
python manage.py makemigrations python manage.py migrate
此类型session的基本文件配置如下,在setting.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,默认修改之后才保存(默认)
session的使用如下:
设置:

获取:

删除:

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失效策略。
(2)缓存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,默认修改之后才保存
(3)文件session
(4)缓存+数据库session
(5)加密cookie session

浙公网安备 33010602011771号