一、分页介绍
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