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