自定义分页(模块化)
自定義分頁(yè)
1、目的&環(huán)境準(zhǔn)備
目的把分頁(yè)寫成一個(gè)模塊的方式然后在需要分頁(yè)的地方直接調(diào)用模塊就行了。
環(huán)境準(zhǔn)備Django中生成一個(gè)APP并且注冊(cè),配置URL&Views
配置URL
from django.conf.urls import url from django.contrib import admin from app01 import viewsurlpatterns = [url(r'^admin/', admin.site.urls),url(r'^user_list/',views.user_list), ]注冊(cè)APP
INSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','app01', ]配置models
from __future__ import unicode_literalsfrom django.db import models# Create your models here.class UserList(models.Model):username = models.CharField(max_length=32)age = models.IntegerField()2、分析
分頁(yè)在基本上行所有的大型網(wǎng)站中都是需要的,比如博客園的分頁(yè),當(dāng)我們查詢的時(shí)候或查看的時(shí)候他有很多博文,難道他是一下把所有的博文都給我們返回的嗎?當(dāng)然不是:如下圖
我們可以根據(jù)提示來(lái)點(diǎn)擊上一頁(yè)和下一頁(yè)或者點(diǎn)擊我們想要查看的頁(yè)面,然后顯示我們要查看的博文鏈接!而不是一下把所有的博文給顯示出來(lái),這樣即節(jié)省流量又能改善用戶體驗(yàn)。
3、逐步完善分頁(yè)代碼
首先咱們先創(chuàng)建500條數(shù)據(jù)(之前不要忘記生成數(shù)據(jù)庫(kù)),在第一訪問(wèn)時(shí)設(shè)置下就OK
3.1、配置views創(chuàng)建數(shù)據(jù)
#/usr/bin/env python #-*- coding:utf-8 -*-from django.shortcuts import render from django.shortcuts import HttpResponse import models # Create your views here.def user_list(request):for i in range(500):dic = {'username': 'name_%d' % i, 'age': i}models.UserList.objects.create(**dic)return HttpResponse('OK')3.2、配置html顯示數(shù)據(jù)并通過(guò)views獲取數(shù)據(jù)顯示
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title></head><body><table>{% for line in result %}<tr><td>{{ line.username }}</td><td>{{ line.age }}</td></tr>{% endfor %}</table><div>{{ pager_str|safe }}</div></body></html>views
def user_list(request):result = models.UserList.objects.all()return render(request,'user_list.html',{'result':result})這樣,前端可以正常顯示咱們?nèi)サ臄?shù)據(jù)了,但是一下子把所有的數(shù)據(jù)都取出來(lái)了。不是咱們想要的結(jié)果。
3.3、取指定的條數(shù)
比如我想取前10條怎么取呢?
def user_list(request):result = models.UserList.objects.all()[0:10]return render(request,'user_list.html',{'result':result})那我讓[0:10]動(dòng)態(tài)起來(lái)就可以了!開(kāi)始和結(jié)尾。
3.4、每頁(yè)顯示10條數(shù)據(jù)
向用戶獲取頁(yè)數(shù),我們可以配置URL在URL中有兩種方式查詢直接在URL中配置正則,然后在views里可以通過(guò)參數(shù)來(lái)獲取用戶傳過(guò)來(lái)的值,
也可以通過(guò)?a=9 &b=10 這樣在Veiws函數(shù)里可以通過(guò)request.GET['a']取值了,并且可以設(shè)置默認(rèn)值request.GET.get('a',0)
def user_list(request):current_page = request.GET.get('page')print current_pageresult = models.UserList.objects.all()[0:10]return render(request,'user_list.html',{'result':result})測(cè)試:
? ?這里的問(wèn)號(hào)是通過(guò)get的方式向后端發(fā)送數(shù)據(jù),我們也可以修改form表單中method改為GET,那么數(shù)據(jù)訪問(wèn)的時(shí)候就是通過(guò)GET方式向后端提交數(shù)據(jù)的,當(dāng)點(diǎn)擊form表單提交數(shù)據(jù)的時(shí)候,form里的內(nèi)容會(huì)自動(dòng)添加到瀏覽器的URL中以上面的格式!
雖然POST和GET都可以向后端提交數(shù)據(jù)但是規(guī)定:GET一般用來(lái)查詢使用,POST一般用來(lái)提交修改數(shù)據(jù)使用,根據(jù)實(shí)際的情況來(lái)定!
看下面的代碼:
def user_list(request):current_page = request.GET.get('page',1)print current_pagestart = 0 #10 20 (current_page-1)*10end = 10 #20 30 current_page*10result = models.UserList.objects.all()[start:end]return render(request,'user_list.html',{'result':result})我們現(xiàn)在讓start & end 動(dòng)態(tài)起來(lái)頁(yè)面動(dòng)態(tài)起來(lái)是不是就更好了?
def user_list(request):current_page = request.GET.get('page',1)current_page = int(current_page)start = (current_page-1)*10 #10 20 (current_page-1)*10end = current_page*10 #20 30 current_page*10result = models.UserList.objects.all()[start:end]return render(request,'user_list.html',{'result':result})然后打開(kāi)網(wǎng)頁(yè)測(cè)試下,修改page的值來(lái)看下顯示效果:
http://127.0.0.1:8000/user_list/?page=2
http://127.0.0.1:8000/user_list/?page=3
http://127.0.0.1:8000/user_list/?page=4 ?
分頁(yè)代碼整理
我們通過(guò)把上面的代碼整理一下整理到函數(shù)或類里下次使用的時(shí)候直接調(diào)用類或者函數(shù)即可。
#/usr/bin/env python #-*- coding:utf-8 -*-from django.shortcuts import render from django.shortcuts import HttpResponse import models # Create your views here.class Pager(object):def __init__(self,current_page):self.current_page = int(current_page)#把方法偽造成屬性(1) @propertydef start(self):return (self.current_page-1)*10@propertydef end(self):return self.current_page*10def user_list(request):current_page = request.GET.get('page',1)page_obj = Pager(current_page)#把方法改造成屬性(2),這樣在下面調(diào)用方法的時(shí)候就不需要加括號(hào)了result = models.UserList.objects.all()[page_obj.start:page_obj.end]return render(request,'user_list.html',{'result':result})2、生成按鈕頁(yè)
上面的功能實(shí)現(xiàn)了分頁(yè)現(xiàn)在,我們是不是可以在下面生成一堆的按鈕來(lái)讓用戶點(diǎn)擊,而不是在瀏覽器中輸入!
先看下如果咱們手動(dòng)寫的話!
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title></head><body><table>{% for line in result %}<tr><td>{{ line.username }}</td><td>{{ line.age }}</td></tr>{% endfor %}</table><div><a href="/user_list/?page=1">1</a><a href="/user_list/?page=2">2</a><a href="/user_list/?page=3">3</a><a href="/user_list/?page=4">4</a><a href="/user_list/?page=5">5</a></div></body></html>如下圖:
?
目的是為了實(shí)現(xiàn)左側(cè)的效果,但是咱們不可能手寫吧?所以應(yīng)該在后臺(tái)創(chuàng)建,這個(gè)是不是就是總共有多少頁(yè)?
需求分析:
每頁(yè)顯示10條數(shù)據(jù)
共500條數(shù)據(jù)就是50頁(yè),那有501條數(shù)據(jù)呢?是多少頁(yè)是51頁(yè)。
可以通過(guò)divmod(500,10),他會(huì)的到一個(gè)元組,第一個(gè)值是值,第二個(gè)值是余數(shù),我們就通過(guò)判斷他是否有余數(shù)來(lái)判斷是否是整頁(yè),如果有余數(shù)在整頁(yè)基礎(chǔ)加1即可!
我們獲取了所有的頁(yè)數(shù)之后可以吧他返回在前端生成,但是這樣我們后端做了分頁(yè)之后前端是不是也做了分頁(yè)操作?
我們可以在后端生成一個(gè)大字符串然后把他返回給前端(拼接的URL)
#/usr/bin/env python #-*- coding:utf-8 -*-from django.shortcuts import render from django.shortcuts import HttpResponse import models # Create your views here.class Pager(object):def __init__(self,current_page):self.current_page = int(current_page)#把方法偽造成屬性(1) @propertydef start(self):return (self.current_page-1)*10@propertydef end(self):return self.current_page*10def user_list(request):current_page = request.GET.get('page',1)page_obj = Pager(current_page)#吧方法未造成屬性(2),這樣在下面調(diào)用方法的時(shí)候就不需要加括號(hào)了result = models.UserList.objects.all()[page_obj.start:page_obj.end]all_item = models.UserList.objects.all().count()all_page,div = divmod(all_item,10)if div > 0:all_page +=1pager_str = ""for i in range(1,all_page+1):#每次循環(huán)生成一個(gè)標(biāo)簽temp = '<a href="/user_list/?page=%d">%d</a>' %(i,i,)#把標(biāo)簽拼接然后返回給前端pager_str += tempreturn render(request,'user_list.html',{'result':result,'pager_str':pager_str})前端配置:
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title></head><body><table>{% for line in result %}<tr><td>{{ line.username }}</td><td>{{ line.age }}</td></tr>{% endfor %}</table><div>{{ pager_str }}</div></body></html>但是有個(gè)問(wèn)題如下圖:
這個(gè)是什么問(wèn)題導(dǎo)致的呢?
咱們?cè)谥暗奈恼聦W(xué)過(guò)一個(gè)CSRF跨站請(qǐng)求偽造的安全設(shè)置,這里還有一個(gè)值得說(shuō)的安全就是XSS攻擊:
XSS攻擊:跨站腳本攻擊(Cross Site Scripting),為不和層疊樣式表(Cascading Style Sheets, CSS)的縮寫混淆,故將跨站腳本攻擊縮寫為XSS。
XSS是一種經(jīng)常出現(xiàn)在web應(yīng)用中的計(jì)算機(jī)安全漏洞,它允許惡意web用戶將代碼植入到提供給其它用戶使用的頁(yè)面中。比如這些代碼包括HTML代碼和客戶端腳本。攻擊者利用XSS漏洞旁路掉訪問(wèn)控制——例如同源策略(same origin policy)。這種類型的漏洞由于被黑客用來(lái)編寫危害性更大的網(wǎng)絡(luò)釣魚(yú)(Phishing)攻擊而變得廣為人知。對(duì)于跨站腳本攻擊,黑客界共識(shí)是:跨站腳本攻擊是新型的“緩沖區(qū)溢出攻擊“,而JavaScript是新型的“ShellCode”。
咱們上面看到的內(nèi)容就是Django為了防止這樣的情況產(chǎn)生而設(shè)置的機(jī)制,例子如下:
如果,寫的簡(jiǎn)單的script可以被保存為HTML標(biāo)簽的話那么?只要有人打開(kāi)這個(gè)頁(yè)面都會(huì)提示一個(gè)信息,這樣是不是不安全,這個(gè)是小的說(shuō)的!
如果說(shuō)這里是一個(gè)獲取Cookie然后發(fā)送到指定服務(wù)器然后服務(wù)器可以通過(guò)cookie訪問(wèn)你的個(gè)人信息是不是就可怕了?!
?那么怎么解決這個(gè)問(wèn)題呢?可以通過(guò)模板語(yǔ)言的一個(gè)函數(shù)來(lái)告訴Django這個(gè)是安全的:加一個(gè)safe (在文章的后面還有一種方法在后端標(biāo)記他是安全的)
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title></head><body><table>{% for line in result %}<tr><td>{{ line.username }}</td><td>{{ line.age }}</td></tr>{% endfor %}</table><div>{{ pager_str|safe }}</div></body></html>效果如下:
這樣全顯示出來(lái)了,不是很好,最好顯示11頁(yè)然后,當(dāng)用戶點(diǎn)擊第6頁(yè)的時(shí)候,這個(gè)6永遠(yuǎn)在中間!所以我們也要讓頁(yè)碼動(dòng)態(tài)起來(lái)!
#/usr/bin/env python #-*- coding:utf-8 -*-from django.shortcuts import render from django.shortcuts import HttpResponse import models # Create your views here.class Pager(object):def __init__(self,current_page):self.current_page = int(current_page)#把方法偽造成屬性(1) @propertydef start(self):return (self.current_page-1)*10@propertydef end(self):return self.current_page*10def page_str(self,all_item,base_url):all_page, div = divmod(all_item, 10)if div > 0:all_page += 1pager_str = ""#默認(rèn)可以看到的頁(yè)碼11個(gè)start = self.current_page - 5end = self.current_page + 6#把頁(yè)面動(dòng)態(tài)起來(lái)傳入起始和結(jié)束for i in range(start, end):#判斷是否為當(dāng)前頁(yè)if i == self.current_page:temp = '<a style="color:red;font-size:26px;padding: 5px" href="%s?page=%d">%d</a>' % (base_url,i,i)else:temp = '<a style="padding: 5px" href="%s?page=%d">%d</a>' % (base_url,i,i)# 把標(biāo)簽拼接然后返回給前端pager_str += tempreturn pager_strdef user_list(request):current_page = request.GET.get('page',1)page_obj = Pager(current_page)#吧方法未造成屬性(2),這樣在下面調(diào)用方法的時(shí)候就不需要加括號(hào)了result = models.UserList.objects.all()[page_obj.start:page_obj.end]all_item = models.UserList.objects.all().count()pager_str = page_obj.page_str(all_item,'/user_list/')return render(request,'user_list.html',{'result':result,'pager_str':pager_str})前端頁(yè)面不用修改了,看效果如下:
現(xiàn)在還是有問(wèn)題的,當(dāng)你現(xiàn)在點(diǎn)擊1,2,3,4,5的時(shí)候因?yàn)榍懊鏇](méi)有頁(yè)面就會(huì)出現(xiàn)負(fù)值!
并且最后一頁(yè)頁(yè)會(huì)出現(xiàn)無(wú)窮大,但是沒(méi)有數(shù)據(jù),那怎么解決呢?
''' 如果總頁(yè)數(shù) <= 11 比如9頁(yè):那么,還有必要讓頁(yè)碼動(dòng)起來(lái)嗎?就沒(méi)必要了直接顯示總共頁(yè)數(shù)就行了!start就是1,end就是9就行了 else:如果當(dāng)前頁(yè)小宇6:start:1end:11如果當(dāng)前頁(yè)大于6:start:當(dāng)前頁(yè)-5end:當(dāng)前頁(yè)+6如果當(dāng)前頁(yè)+6 >總頁(yè)數(shù):start:總頁(yè)數(shù)-10end:總頁(yè)數(shù) '''修改后的代碼:
#/usr/bin/env python #-*- coding:utf-8 -*-from django.shortcuts import render from django.shortcuts import HttpResponse import models # Create your views here.class Pager(object):def __init__(self,current_page):self.current_page = int(current_page)#把方法偽造成屬性(1) @propertydef start(self):return (self.current_page-1)*10@propertydef end(self):return self.current_page*10def page_str(self,all_item,base_url):all_page, div = divmod(all_item, 10)if div > 0:all_page += 1pager_str = ""# #默認(rèn)可以看到的頁(yè)碼11個(gè)# # start = self.current_page - 5# end = self.current_page + 6# # #把頁(yè)面動(dòng)態(tài)起來(lái)傳入起始和結(jié)束# for i in range(start, end):# # #判斷是否為當(dāng)前頁(yè)# if i == self.current_page:# temp = '<a style="color:red;font-size:26px;padding: 5px" href="%s?page=%d">%d</a>' % (base_url,i,i)# else:# temp = '<a style="padding: 5px" href="%s?page=%d">%d</a>' % (base_url,i,i)# # # 把標(biāo)簽拼接然后返回給前端# pager_str += tempif all_page <= 11:start = 1end = all_pageelse:if self.current_page <= 6:start = 1end = 11 + 1else:start = self.current_page - 5end = self.current_page + 6if self.current_page + 6 > all_page:start = all_page - 10end = all_page + 1#把頁(yè)面動(dòng)態(tài)起來(lái)傳入起始和結(jié)束for i in range(start, end):#判斷是否為當(dāng)前頁(yè)if i == self.current_page:temp = '<a style="color:red;font-size:26px;padding: 5px" href="%s?page=%d">%d</a>' % (base_url,i,i)else:temp = '<a style="padding: 5px" href="%s?page=%d">%d</a>' % (base_url,i,i)# 把標(biāo)簽拼接然后返回給前端pager_str += tempreturn pager_strdef user_list(request):current_page = request.GET.get('page',1)page_obj = Pager(current_page)#把方法改造成屬性(2),這樣在下面調(diào)用方法的時(shí)候就不需要加括號(hào)了result = models.UserList.objects.all()[page_obj.start:page_obj.end]all_item = models.UserList.objects.all().count()pager_str = page_obj.page_str(all_item,'/user_list/')return render(request,'user_list.html',{'result':result,'pager_str':pager_str})這樣簡(jiǎn)單分頁(yè)就完成了,現(xiàn)在我們可以在給他增加一個(gè)“上一頁(yè)” & 下一頁(yè)
我們可以把他給為一個(gè)列表,然后每次生成的標(biāo)簽append到列表中,然后分別在列表中最前面和后面增加,上一頁(yè)和下一頁(yè)
#/usr/bin/env python #-*- coding:utf-8 -*-from django.shortcuts import render from django.shortcuts import HttpResponse import models # Create your views here.class Pager(object):def __init__(self,current_page):self.current_page = int(current_page)#把方法偽造成屬性(1) @propertydef start(self):return (self.current_page-1)*10@propertydef end(self):return self.current_page*10def page_str(self,all_item,base_url):all_page, div = divmod(all_item, 10)if div > 0:all_page += 1pager_list = []if all_page <= 11:start = 1end = all_pageelse:if self.current_page <= 6:start = 1end = 11 + 1else:start = self.current_page - 5end = self.current_page + 6if self.current_page + 6 > all_page:start = all_page - 10end = all_page + 1#把頁(yè)面動(dòng)態(tài)起來(lái)傳入起始和結(jié)束for i in range(start, end):#判斷是否為當(dāng)前頁(yè)if i == self.current_page:temp = '<a style="color:red;font-size:26px;padding: 5px" href="%s?page=%d">%d</a>' % (base_url,i,i)else:temp = '<a style="padding: 5px" href="%s?page=%d">%d</a>' % (base_url,i,i)# 把標(biāo)簽拼接然后返回給前端 pager_list.append(temp)#上一頁(yè)if self.current_page > 1:pre_page = '<a href="%s?page=%d">上一頁(yè)</a>' % (base_url, self.current_page - 1)else:# javascript:void(0) 什么都不干pre_page = '<a href="javascript:void(0);">上一頁(yè)</a>'#下一頁(yè)if self.current_page >= all_page:next_page = '<a href="javascript:void(0);">下一頁(yè)</a>'else:next_page = '<a href="%s?page=%d">下一頁(yè)</a>' % (base_url, self.current_page + 1)pager_list.insert(0, pre_page)pager_list.append(next_page)return "".join(pager_list)def user_list(request):current_page = request.GET.get('page',1)page_obj = Pager(current_page)#把方法改造成屬性(2),這樣在下面調(diào)用方法的時(shí)候就不需要加括號(hào)了result = models.UserList.objects.all()[page_obj.start:page_obj.end]all_item = models.UserList.objects.all().count()pager_str = page_obj.page_str(all_item,'/user_list/')return render(request,'user_list.html',{'result':result,'pager_str':pager_str})最后寫成模塊,也可以吧分頁(yè)的數(shù)量動(dòng)態(tài)化!
?
前面說(shuō)過(guò)關(guān)于XSS的問(wèn)題,還有一種方式在后端告訴他是安全的即可,前端就不需要標(biāo)記了。
導(dǎo)入并使用模塊即可:
#!/usr/bin/env python #-*- coding:utf-8 -*-from django.utils.safestring import mark_safe#把拼接的HTML標(biāo)記為安全的即可return mark_safe("".join(pager_list))<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title></head><body><table>{% for line in result %}<tr><td>{{ line.username }}</td><td>{{ line.age }}</td></tr>{% endfor %}</table><div>{{ pager_str }}</div></body></html>#!/usr/bin/env python #-*- coding:utf-8 -*-from django.utils.safestring import mark_safeclass Pager(object):def __init__(self,current_page):self.current_page = int(current_page)#把方法偽造成屬性(1) @propertydef start(self):return (self.current_page-1)*10@propertydef end(self):return self.current_page*10def page_str(self,all_item,base_url):all_page, div = divmod(all_item, 10)if div > 0:all_page += 1pager_list = []if all_page <= 11:start = 1end = all_pageelse:if self.current_page <= 6:start = 1end = 11 + 1else:start = self.current_page - 5end = self.current_page + 6if self.current_page + 6 > all_page:start = all_page - 10end = all_page + 1#把頁(yè)面動(dòng)態(tài)起來(lái)傳入起始和結(jié)束for i in range(start, end):#判斷是否為當(dāng)前頁(yè)if i == self.current_page:temp = '<a style="color:red;font-size:26px;padding: 5px" href="%s?page=%d">%d</a>' % (base_url,i,i)else:temp = '<a style="padding: 5px" href="%s?page=%d">%d</a>' % (base_url,i,i)# 把標(biāo)簽拼接然后返回給前端 pager_list.append(temp)#上一頁(yè)if self.current_page > 1:pre_page = '<a href="%s?page=%d">上一頁(yè)</a>' % (base_url, self.current_page - 1)else:# javascript:void(0) 什么都不干pre_page = '<a href="javascript:void(0);">上一頁(yè)</a>'#下一頁(yè)if self.current_page >= all_page:next_page = '<a href="javascript:void(0);">下一頁(yè)</a>'else:next_page = '<a href="%s?page=%d">下一頁(yè)</a>' % (base_url, self.current_page + 1)pager_list.insert(0, pre_page)pager_list.append(next_page)return mark_safe("".join(pager_list))來(lái)源:?http://www.cnblogs.com/luotianshuai/p/5377233.html
來(lái)自為知筆記(Wiz)
轉(zhuǎn)載于:https://www.cnblogs.com/bruceg/p/5553770.html
總結(jié)
以上是生活随笔為你收集整理的自定义分页(模块化)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 使用U盘在Mac机上装win8.1系统
- 下一篇: js中的预解释