Django分页、Ajax
一、Django的分頁:
分頁是為了減少一次性從數(shù)據(jù)庫讀過多的數(shù)據(jù)。
先說一下offset和limit。
語句1:select * from student limit 9,4 語句2:slect * from student limit 4 offset 9這兩條語句的查詢結(jié)果是一樣的。同樣可以完成分頁的功能。1、Django內(nèi)置分頁:?
from django.core.paginator import EmptyPage,PageNotAnInteger,Paginatordef index(request):current_page = request.GET.get("current_page")if current_page == None:current_page = 1paginator = Paginator(slist, 10) # slist是數(shù)據(jù),10代表每一頁的顯示多少條# 這個(gè)page對象包含了,是否具有上一頁,是否有下一頁page = paginator.page(current_page) # 在這里做異常判斷,如果用戶輸入不合法就報(bào)異常return render(request, "index.html", {"slist": page, "current_page": current_page})前端頁面:
# 循環(huán)打印數(shù)據(jù) <ul>{% for row in slist.object_list %} # 已經(jīng)分好頁的數(shù)據(jù)<li>{{ row.name }}</li>{% endfor %} </ul># 判斷是否有上一頁 {% if slist.has_previous %}# 上一頁的頁碼<a href="/index?current_page={{ slist.previous_page_number }}">上一頁</a> {% endif %} 總頁數(shù){{ slist.paginator.num_pages }}, 當(dāng)前頁:{{ slist.number }}# 判斷是否有下一頁 {% if slist.has_next %}# 下一頁的頁碼<a href="/index?current_page={{ slist.next_page_number }}">下一頁</a> {% endif %}兩個(gè)重要的對象: Paginator 和?page對象。
Paginator:
per_page: 每頁顯示記錄數(shù)量count: 數(shù)據(jù)總個(gè)數(shù)num_pages: 總頁數(shù)page_range: 總頁數(shù)的索引范圍,如: (1,10),(1,200)page: page對象 page(2) 代表第二頁數(shù)據(jù)的對象?page:
has_next 是否有下一頁next_page_number 下一頁頁碼has_previous 是否有上一頁previous_page_number 上一頁頁碼object_list 分頁之后的當(dāng)前頁數(shù)據(jù)列表number 當(dāng)前頁paginator paginator對象,父類對象※:可以建一個(gè)模板,每次分頁都include,提高代碼的可重用性。至此Django的內(nèi)置分頁已做好,并沒有什么樣式,下面開始自定制。
2、擴(kuò)展Dajngo的內(nèi)置分頁:
通過繼承Paginator的方式進(jìn)行自定義類的方式進(jìn)行分頁。
def index(request):current_page = request.GET.get("current_page")if current_page == None:current_page = 1# 參數(shù):當(dāng)前頁、頁碼最大顯示、數(shù)據(jù)列表、每頁多少數(shù)據(jù)paginator = CustomPaginator(current_page, 5, slist, 10)page = paginator.page(current_page) # 在這里應(yīng)該做異常判斷,如果用戶輸入不合法就報(bào)異常return render(request, "index.html", {"slist": page, "current_page": current_page})class CustomPaginator(Paginator):# 初始化調(diào)用父類的方法def __init__(self, current_page, per_num, *args, **kwargs):self.current_page = int(current_page)self.per_page = per_numsuper().__init__(*args, **kwargs)# 自己定義一個(gè)方法進(jìn)行頁碼的顯示def getNum(self):self.part = self.per_page//2# 當(dāng)前頁碼數(shù)小于總頁數(shù)if self.num_pages < self.per_page:return range(1,self.num_pages+1)# 當(dāng)前頁小于顯示頁碼的一半時(shí)if self.current_page <= self.part:return range(1, self.per_page+1)# 當(dāng)當(dāng)前頁加上顯示的頁碼一半大于總頁數(shù)時(shí)if (self.current_page+self.part) > self.num_pages:return range(self.num_pages-self.per_page+1,self.num_pages+1)# 當(dāng)前頁大于顯示頁碼的一半時(shí)if self.current_page > self.part:return range(self.current_page-self.part, self.current_page+self.part+1)前端頁面:
# 進(jìn)行數(shù)據(jù)的遍歷 <ul>{% for row in slist.object_list %}<li>{{ row.name }}</li>{% endfor %} </ul># 進(jìn)行頁碼遍歷 {% if slist.has_previous %}<a href="/index?current_page={{ slist.previous_page_number }}">上一頁</a> {% endif %} {% for item in slist.paginator.getNum %}{% if item == slist.number %}<a href="/index?current_page={{ item }}" style="font-size: 40px">{{ item }}</a>{% else %}<a href="/index?current_page={{ item }}">{{ item}}</a>{% endif %} {% endfor %} {% if slist.has_next %}<a href="/index?current_page={{ slist.next_page_number }}">下一頁</a> {% endif %}</body>3、自定義分頁:
通過自己寫分頁的類。
class Paginator(object):# 參數(shù): 每頁的記錄數(shù)、當(dāng)前頁碼、顯示最大頁碼數(shù)、總數(shù)據(jù)條數(shù)def __init__(self, per_count_page, current_page, per_index_page, total_count):self.per_count_page = per_count_pageself.current_page = int(current_page)self.per_index_page = per_index_pageself.total_count = total_countself.mid = self.per_index_page//2# 開始頁數(shù)def start(self):return (self.current_page - 1) * self.per_count_page# 結(jié)束頁數(shù)def end(self):return self.current_page * self.per_count_page# 計(jì)算總頁數(shù)@propertydef page_num(self):self.a, b = divmod(self.total_count, self.per_count_page)if b != 0:return self.a+1 # 在這里最好直接返回一個(gè)值,而不是當(dāng)前的形式else:return self.a# 計(jì)算頁碼顯示樣式def getNum(self): # self.part = self.per_page//2# 當(dāng)前頁碼數(shù)小于總頁數(shù)if self.page_num < self.per_index_page:return range(1, self.page_num+1)if self.current_page <= self.mid:return range(1, self.per_index_page+1)if (self.current_page+self.mid) > self.page_num:return range(self.page_num-self.per_index_page+1,self.page_num+1)if self.current_page > self.mid:return range(self.current_page-self.mid, self.current_page+self.mid+1)# 將每個(gè)a標(biāo)簽放入,列表中,前端頁面不用再循環(huán)顯示def page_indexs(self):index_list = []first = '<a href="/index1?current_page=1">首頁</a>'index_list.append(first)if self.current_page-1:top = '<a href="/index1?current_page=' + str(self.current_page - 1) + '">上一頁</a>'index_list.append(top)for i in self.getNum():# 尋找當(dāng)前頁if self.current_page == i:temp = '<a style="font-size: 30px" href="/index1?current_page='+str(i)+'">'+str(i)+'</a>'else:temp = '<a href="/index1?current_page='+str(i)+'">'+str(i)+'</a>'index_list.append(temp)if self.current_page != (self.a+1):bottom = '<a href="/index1?current_page=' + str(self.current_page + 1) + '">下一頁</a>'index_list.append(bottom)last = '<a href="/index1?current_page=' + str(self.a+1) + '">尾頁</a>'index_list.append(last)return "".join(index_list) # 轉(zhuǎn)換成字符串前端頁面:
<body> # 進(jìn)行數(shù)據(jù)遍歷 <ul>{% for row in data %}<li>{{ row.name}}</li>{% endfor %} </ul> # 后臺遍歷好了,直接顯示 {{ pages|safe }} </body>更多內(nèi)容詳見:https://docs.djangoproject.com/en/2.2/topics/pagination/
二、Ajax部分
1、概述:Ajax 的全稱是Asynchronous JavaScript and XML(異步 JavaScript 和 XML),是指一種創(chuàng)建交互式網(wǎng)頁應(yīng)用的網(wǎng)頁開發(fā)技術(shù)。是一種用于創(chuàng)建快速動態(tài)網(wǎng)頁的技術(shù),是一種在無需重新加載整個(gè)網(wǎng)頁的情況下,能夠更新部分網(wǎng)頁的技術(shù)。
2、基本原理
3、$.ajax的一般格式
$.ajax({url:“路徑”,data:{key1:value1}, // value1可以是數(shù)組類型,但不能是字典類型,如果非要傳字典類型就把字典傳成字符串type:'POST/GET', //數(shù)據(jù)的提交方式:get和postdataType:’json’, // 數(shù)據(jù)的返回值類型,當(dāng)返回的數(shù)據(jù)類型和dataType定義不一樣時(shí),不會觸發(fā)success函數(shù)。traditional:True,success:function(str){ //成功回調(diào)函數(shù),str就是后臺傳送回來的信息。在回調(diào)函數(shù)中無法用$(this) 會無法定位到準(zhǔn)確位置},error:function (err){ //失敗回調(diào)函數(shù)} });dataType 的一些參數(shù)值:
當(dāng)dataType:"json"時(shí),會自動解析json字符串。當(dāng)dataType:"text"時(shí),不會進(jìn)行任何處理。默認(rèn)就是text。當(dāng)dataType:"xml"時(shí),會自動轉(zhuǎn)化為xml。dataType也可以是html一些其他的屬性:
var data = $("表單的id").serialize() // serialize()方法會自動提交表單的屬性到data下。后臺接收到的數(shù)據(jù): <QueryDict: {'slist': ['name=%E6%94%BE%E5%88%B0&pass=123&chose=third']}>Ajax傳數(shù)組數(shù)據(jù)時(shí):data:{slist:[1,2,3,4,5]} 后臺收到的是 <QueryDict: {'slist[]':['first', 'second']}> ,這樣是不符合常理的。 當(dāng)設(shè)置traditional:true。后臺接收到的數(shù)據(jù)<QueryDict: {'slist': ['first', 'second']}>比較Ajax和跳轉(zhuǎn)新頁面:
新url的方式進(jìn)行修改: ?好處是 獨(dú)立的頁面,數(shù)據(jù)量大、或者條目多的時(shí)候適合用。當(dāng)用戶輸入錯(cuò)誤時(shí)應(yīng)該保留用戶輸入的正確字段。
Ajax方式進(jìn)行修改:數(shù)據(jù)量小、或者條目少的時(shí)候適合用。是否刷新?一般刷新,除非性能要求。要考慮當(dāng)前頁碼和自定義屬性。
原生的Ajax:
為了解決手機(jī)app調(diào)用Ajax的問題,所以用原生的Ajax。
GET請求:
var xhr = new XMLhttprequest() // 創(chuàng)建一個(gè)對象xhr.open("GET","") // open方法的兩個(gè)參數(shù) 請求的方式,路徑xhr.onreadystatechange = function(){ // 回調(diào)函數(shù)if(xhr.readyState==4){ // 當(dāng)readyState返回值為4時(shí)表示成功 console.log("接收成功")} } xhr.send(null) // 發(fā)送數(shù)據(jù)POST請求:
var xhr = new XMLhttprequest() // 創(chuàng)建一個(gè)對象xhr.open("POST","") // open方法的兩個(gè)參數(shù) 請求的方式,路徑xhr.onreadystatechange = function(){ // 回調(diào)函數(shù)if(xhr.readyState==4){ // 當(dāng)readyState返回值為4時(shí)表示成功 console.log("接收成功")} } xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded;charset-UTF-8") // 需要設(shè)置請求頭否則django不認(rèn)識 xhr.send("name=default") // 發(fā)送數(shù)據(jù)偽Ajax請求:
通過iframe的無刷新返回?cái)?shù)據(jù)的特性,并且能很好的解決兼容性的問題,所以有時(shí)候通過偽Ajax請求的方式。
首先在form標(biāo)簽加上target屬性,target的值是iframe的name屬性的值。
<form method="post" action="" enctype="multipart/form-data" target="iframe">還需要為iframe標(biāo)簽綁定onload屬性,不過不直接寫在標(biāo)簽上,而是當(dāng)點(diǎn)擊提交以后通過 js 進(jìn)行綁定。onload屬性相當(dāng)于回調(diào)函數(shù)。
document.getElementById("iframe").onload = reloading;處理iframe的返回值:拿到后臺返回的值
原生的js方式:document.getElementById("iframe").contentWindow.document.body.innerHTMLjQuery的方式:$("#iframe").contents().find("body").html()Ajax文件上傳:
我們可以為上傳按鈕進(jìn)行onchange函數(shù)的定義;
<input type="file" onchange="change()"> // 當(dāng)選中文件以后自動上傳原生Ajax:
var data = new Formdata(); // 通過Formdata的方式進(jìn)行上傳 data.append("img", document.getElementById("load").files[0]) // 獲取文件標(biāo)簽的內(nèi)容 var xhr = new XMLHttpRequest(); xhr.open("post","/upload"); xhr.onreadystatechange() = function(){if(xhr.readystate == 4){console.log(xhr.responseText)} } xhr.send(data); // 在這里直接進(jìn)行發(fā)送jQuery:
var data = new Formdata(); data.append("img", $("#load")[0].files[0]) $.ajax({url:"/upload",type:"POST",data:data,success:function(arg){console.log(arg)}processData: false, // 告訴jQuery不要去處理發(fā)送的數(shù)據(jù), 發(fā)送對象。contentType: false, // 告訴jQuery不要去設(shè)置Content-Type請求頭 })iframe的形式上傳文件:?
HTML:<iframe style="display: none" id="if" name="frame"></iframe> <form id="form_data" method="post" action="/files/" enctype="multipart/form-data" target="frame"><div id="up"><span>預(yù)覽</span></div><input type="file" name="img" onchange="upload()"><input type="text"> </form>-------------------------------------------------------------------------js:function upload() {document.getElementById("if").onload = show;document.getElementById("form_data").submit()}function show() {var x=this.contentWindow.document.body.innerHTM;document.getElementById("up").innerHTML = "<img src="+new_x.path+">"}跨域Ajax請求:
由于瀏覽器有同源策略的限制,所以無法正常接收其他服務(wù)器的響應(yīng)信息。所以通過src屬性進(jìn)行跨域訪問。我們通過jsonp的方式進(jìn)行苦于的訪問。以jsonp的形式進(jìn)行跨域訪問,只能以GET的方式進(jìn)行。
原生js:
js部分function show1(){var img = document.createElement("script"); // 創(chuàng)建一個(gè)script標(biāo)簽img.src = " http://127.0.0.1:8080/outer"; // 設(shè)置請求路徑document.head.appendChild(img); // 在頭內(nèi)添加信息document.head.removeChild(img); // 拿到數(shù)據(jù)就刪除}function fuck(msg) {console.log(msg)}------------------------------------------------------------------- viewsdef outer(request):return HttpResponse("fuck('外界的響應(yīng)')") // 返回一個(gè)函數(shù)名包裹信息,實(shí)際上返回的是函數(shù)jQuery:
js部分function show1(){$.ajax({url:" http://127.0.0.1:8080/outer",type:"get",success:function (msg) {console.log(msg)},dataType:"jsonp", // 當(dāng)類型是jsonp的形式時(shí),會自動生成標(biāo)簽等jsonp:"callback", // 設(shè)置參數(shù)名jsonpcallback:"fuck", // 設(shè)置回調(diào)函數(shù)})}function fuck(msg) {console.log(msg)}------------------------------------------------------------------- viewsdef outer(request):name = request.GET.get("callback") // 獲取參數(shù)值return HttpResponse(name+"('外界的響應(yīng)')") // 返回一個(gè)函數(shù)名包裹信息跨站資源共享(core):
通過設(shè)置頭信息,讓瀏覽器不再限制信息的返回,core的方式既可以GET請求也可以用POST請求
function show1(){$.ajax({url:"http://127.0.0.1:8080/outer/",type:"get",success:function (msg) {$("#content").text(msg);}}) }-----------------------------------------------views視圖函數(shù):?
總結(jié)
以上是生活随笔為你收集整理的Django分页、Ajax的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2022年全球市场心跳异常检测设备总体规
- 下一篇: 数字电路学习笔记(一)