分页
分页的实现,是由我们自己写的后端代码组建而成,这段写的代码可以直接放在以后的任何分页结构中使用。
先来谈谈原始逻辑:
主页代码如下:
1 <!DOCTYPE html> 2 <html lang="zh-CN"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 6 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> 7 <title>Title</title> 8 <link rel="stylesheet" href="/static/dist/css/bootstrap.min.css"> 9 <script src="/static/dist/js/bootstrap.min.js"></script> 10 <script src="/static/jquery-3.2.1.min.js"></script> 11 </head> 12 <body> 13 <div class="container"> 14 <h5>欢迎登录:<span>{{ user }}</span></h5> 15 <table class="table table-bordered"> 16 <thead> 17 <tr> 18 <th>id</th> 19 <th>姓名</th> 20 </tr> 21 </thead> 22 <tbody> 23 24 {% for item in list %} 25 <tr> 26 <td>{{ item.id }}</td> 27 <td>{{ item.name }}</td> 28 </tr> 29 {% endfor %} 30 31 </tbody> 32 33 </table> 34 <div style="text-align: center"> 35 <ul class="pagination"> 36 {% for item in page_fen %} 37 {{ item|safe }} 38 {% endfor %} 39 40 </ul> 41 </div> 42 </div> 43 </body> 44 </html>
用模板语言,在后端通过for循环伪造了302条数据,在前端渲染出来。
我们拿到了302条数据之后,首先要想的,是这些数据该分成多少页?由此,便有了一下推想。
首先,我们要想在前端的数据中,我们是怎么区分用户选择的页码的?所以,我们要用到的方法就是GET,通过GET中拼接的url取到?后面的我们所赋予的数值,这样就可以判断用户要浏览的数据页面是
多少页。
1 d_page=int(request.GET.get("name",1))
这样就是我们要取到的页码的值。
接下来我们要设想的,就是每一页中,我们要存放多少条数据?因为只有判断出了每一页存放数据的上限,我们才好将数据进行分页显示。
1 put_page=10 2 start=(d_page-1)*put_page 3 end=(d_page)*put_page 4 lip = li[start:end]
代码中,put_page的含义是我们在每一页要存放的数据量,在这里我设定的数据量是10.
下面数据是从数据中的什么地方开始计算的十条数据?我们就要用到python中的切片,起始的数据值和结束的数据值就是通过我们在之前从GET中所去到的当前页码来计算的。
例如我一共伪造了302条数据,我要去到第一页的十条数据,那么我的数据索引就是[0,10],第二页就是[10,20]有了数字就好计算了。
我们取第一页得到的页码自然就是1那么,我们的数据索引就可以看成是
[1-1*put_page,1*put_page]
因为我们设定的数据量是10,所以得到的数据刚好是[0,10]符合我们的要求,再实验第二页的数据
[2-1*put_page,2*put_page] 结果我们发现,得到的数据又恰巧符合我们的结果,所以我们的start和end就可以按照这个方法来取值了,这样,我们就实现了截取每一页要显示的数据的功能
每一页显示的数据量做好了,接下来该思考的,就是怎么编排页码的问题了。
通过bootstrap我们可以直接得到分页div的模型,那么我们怎么判断我们该有多少页码?怎么实现页码与网页的对应呢?
基于这个需求,我编译了以下代码:
1 page_xi = 11 2 all_c = len(li) 3 all_page, tem = divmod(all_c, put_page) 4 if tem: 5 all_page += 1 6 pa_half=int((page_xi-1)/2) 7 if d_page<=pa_half: 8 pager_start=1 9 pager_end = page_xi 10 elif d_page>=all_page-pa_half: 11 pager_start = all_page-page_xi 12 pager_end = all_page 13 else: 14 pager_start=d_page-pa_half 15 pager_end=d_page+pa_half 16 page_fen=[] 17 first='<li><a href="%s?name=1">首页</a></li>' % (request.path_info) 18 page_fen.append(first) 19 if d_page>1: 20 prev = '<li><a href="%s?name=%s">上一页</a></li>' % (request.path_info,d_page-1) 21 page_fen.append(prev) 22 for i in range(pager_start, pager_end+1): 23 if i == d_page: 24 temp = '<li class="active"><a href="%s?name=%s">%s</a></li>' % (request.path_info, i, i,) 25 else: 26 temp = '<li><a href="%s?name=%s">%s</a></li>' % (request.path_info, i, i,) 27 page_fen.append(temp) 28 if d_page<all_page: 29 prev = '<li><a href="%s?name=%s">下一页</a></li>' % (request.path_info, d_page + 1) 30 page_fen.append(prev) 31 last = '<li><a href="%s?name=%s">尾页</a></li>' % (request.path_info,all_page) 32 page_fen.append(last) 33 return render(request,"class.html",{"list":lip,"page_fen":page_fen,"user":user})
其中page_xi的含义就是我在每一页要显示的页码中,规定成了11个,然后我们又通过len()方法,获取了数据的总长度,这样我们先通过总数据用divmod的方法,与put_page进行计算,的出来的就是
余数与商,我们这时候就可以判断,如果有余数的话,那么我们就要多给这条数据余出来一页来显示数据,如果没有那么商就是我们需要的总页码。
这个时候,我们使用循环来将标签append进列表,再由模板语言循环渲染的话,就可以的出来所有的页码。
但是,我们之前设定了page_xi来限制页码的数量还没有用到,那么它是做什么的呢?别着急,他当然有大的作用。
数据少的话,我们倒不会觉得有什么问题,但是数据量一多,我们甚至会有几百个页码,那么,我们难道要让他一个贴一个的拍下来嘛?这时候page_xi就要发挥它的作用了,我们是利用他来限制每页所要
显示的页码数量的。
我们通过它减去1除以2也就是代码中的:pa_half=int((page_xi-1)/2)就可以得到pa_half,那么问题来了,pa_half又是做什么用的呢?让我们来一步一步的分析。
假设我们让所已经选择的页码处在这一条页码的最中央,那么前面的一堆页码和后面的一堆页码,加上我所选择的页码加起来就要在我所限定的page_xi以内,所以我们就要获得在我们选择的页码前要展示的
页码数量,与在选择的页码后要展示的页码数量,所以pa_half就是我们所计算的页码数量,也就是我们限定的11个页码值将所选择的一个除外的前后各5个。
这样我们就可以设定页码条所展示的start值和end值了。
但是,这时候还有一个问题,如果我们选择的是第一页或者是尾页呢?它们的前后并没有各5个页码。
没关系,在这个时候我们要加上判断,也就是判断当前所选择的页码是否大于等于我们所设定这个前后页码长度。如果是小于等于的话,那么这个页码值肯定是在5页以内,我们就而已直接用1~11的页码值来表示。
如果这个页码值大于(我们所有页码值减去我们所设定这个前后页码长度)那么它肯定是在最后5页,那么我们直接将end值设为最后一页,start设定为最后一页减去设定的11就好了。
最后我们利用列表的方式,将创建标签的字符串传给模板语言,然后渲染即可。
当然,这么长的代码,如果我以后很多项目都要用到怎么办?很简单,那么我们就自己写一个类,以后用到的时候自己实例化调用就好了,具体类方法:
1 #使用方法: 2 # d_page=int(request.GET.get("name",1)) 3 # obj=Pagation(d_page,10,11,len(li),request.path_info) #分别要传的值(当前页,每一页放多少数据,每一页放多少个跳转按钮,数据的长度,当前的url) 4 # 5 # lip = li[obj.start:obj.end] #直接引用strat和end方法获取每一页数据的头和尾 6 # page_fen=obj.huobiao() #huobiao方法获取底下该出来的跳转分页码 7 # return render(request, "class.html", {"list": lip, "page_fen": page_fen, "user": user}) 8 9 10 11 class Pagation(object): 12 def __init__(self, d_page,put_page,page_xi,all_c,r_url): 13 self.d_page=d_page 14 self.put_page=put_page 15 self.page_xi=page_xi 16 self.all_c=all_c 17 self.r_url=r_url 18 @property 19 def start(self): 20 start = (self.d_page - 1) * self.put_page 21 return start 22 @property 23 def end(self): 24 end = (self.d_page) * self.put_page 25 return end 26 def huobiao(self): 27 all_page, tem = divmod(self.all_c, self.put_page) 28 if tem: 29 all_page += 1 30 pa_half = int((self.page_xi - 1) / 2) 31 if self.d_page <= pa_half: 32 pager_start = 1 33 pager_end = self.page_xi 34 elif self.d_page >= all_page - pa_half: 35 pager_start = all_page - self.page_xi 36 pager_end = all_page 37 else: 38 pager_start = self.d_page - pa_half 39 pager_end = self.d_page + pa_half 40 page_fen = [] 41 first = '<li><a href="%s?name=1">首页</a></li>' % (self.r_url) 42 page_fen.append(first) 43 if self.d_page > 1: 44 prev = '<li><a href="%s?name=%s">上一页</a></li>' % (self.r_url, self.d_page - 1) 45 page_fen.append(prev) 46 for i in range(pager_start, pager_end + 1): 47 if i == self.d_page: 48 temp = '<li class="active"><a href="%s?name=%s">%s</a></li>' % (self.r_url, i, i,) 49 else: 50 temp = '<li><a href="%s?name=%s">%s</a></li>' % (self.r_url, i, i,) 51 page_fen.append(temp) 52 if self.d_page < all_page: 53 prev = '<li><a href="%s?name=%s">下一页</a></li>' % (self.r_url, self.d_page + 1) 54 page_fen.append(prev) 55 last = '<li><a href="%s?name=%s">尾页</a></li>' % (self.r_url, all_page) 56 page_fen.append(last) 57 return page_fen
使用方法见注释。
session
session的使用方法很简单,主要是利用原理。
当我们使用session的时候,在每次登陆成功后,就可以将用户名存入session中。
1 def login(request): 2 if request.method=="POST": 3 usname=request.POST.get("username") 4 pwd=request.POST.get("password") 5 if usname=="gaoshengyue"and pwd=="gsy121994": 6 request.session["username"]=usname 7 return redirect("/class/") 8 error_msg="输入错误" 9 return render(request, "zuoye.html", {"error": error_msg}) 10 return render(request,"zuoye.html")
session帮我们做成的流程是:
使用request.session["username"]
生成随机字符串
发给用户,写到用户浏览器的cookie中
自己保留一份: {username:'alex',id:1}
在我们使用session前,有两条命令一定要执行,因为他回在我们的项目数据库中建一个session的表用来存放数据
python manage.py makemigrations
python manage.py migrate
这样我们存入session的就是用户名了
我们在取的时候,直接用request.session.get("username")就可以
注销的时候删除这个session : request.session.delete()
session与cookie做比较的话,session比较安全,因为是生成一个随机字符串,自己这里保存一份,放在用户那里一份,相当于一个身份牌,让客户拿着身份牌来验证,然而cookie的话,会直接存在
用户那里,那样的话信息的安全性大大减少。不过因为cookie不会再自己这里存放数据,所以验证速度快,session的速度要比cookie慢。
注销:
1 def logout(request): 2 # 获取当前用户的随机字符串 3 # 在数据库中将当前数据删除 4 request.session.delete() 5 6 # del request.session['username'] 7 8 return redirect('/login/')