Django之AJAX簡介

AJAX簡介

AJAX(Asynchronous Javascript And XML)翻譯成中文就是「異步的Javascript和XML」。即便用Javascript語言與服務器進行異步交互,傳輸的數據爲XML(固然,傳輸的數據不僅是XML)。前端

AJAX 不是新的編程語言,而是一種使用現有標準的新方法。其實就是基於js寫的一個功能模塊而已python

因爲原生js書寫ajax較爲繁瑣 因此咱們直接學jQuery封裝號的ajax模塊操做ajax

AJAX 最大的優勢是:異步提交,局部刷新數據庫

在不從新加載整個頁面的狀況下,能夠與服務器交換數據並更新部分網頁內容。(這一特色給用戶的感覺是在不知不覺中完成請求和響應過程)

AJAX 不須要任何瀏覽器插件,但須要用戶容許JavaScript在瀏覽器上執行。django

同步交互:任務提交以後原地等待任務的返回結果 進程表現上來講 阻塞
異步交互:任務提交以後不須要原地等待返回結果 直接執行下一行代碼  進程表現上來講 非阻塞
        任務的結果經過異步回調機制 callback()

案例:用戶名在時時和後端交互,可是頁面沒有刷新。用戶體驗更好編程

前端與後端的交互方式有:json

1.瀏覽器窗口輸入url回車                    GET
2.a標籤href屬性填寫url點擊                 GET
3.form表單                             GET/POST
4.Ajax                                    GET/POST

AJAX基本語法結構

小案例:後端

初識ajax
    案例:頁面上有三個input框 一個按鈕
    用戶在前兩個框中輸入數字 點擊按鈕保證頁面不刷新的狀況下將數據發到後端作計算
    將計算好的結果再發給前端展現到第三個input框中

效果:瀏覽器

def index(request):
    if request.method == 'POST':
        i1 = request.POST.get('i1')
        i2 = request.POST.get('i2')
        # i1 和 i2 是字符串類型  須要先作類型轉換
        i3 = int(i1) + int(i2)
        return HttpResponse(i3)
    return render(request,'index.html')
ajax基本語法結構
        // ajax基本語法
        $.ajax({
                    // 1.到底朝哪一個後端提交數據
            url:'',  // 控制數據的提交路徑  有三種寫法 跟form表單的action屬性一致
            type:'post',  // 2.指定當前請求方式
            data:{'i1':$('#i1').val(),'i2':$('#i2').val()},  // 3.提交的數據
                        // 4.ajax是異步提交 因此須要給一個回調函數來處理返回的結果
            success:function (data) {  // data就是異步提交的返回結果
                // 將異步回調的結果經過DOM操做渲染到第三個input框中
                $('#i3').val(data)
            }
        })

先後端交互的數據編碼格式

urlencoded
formdata
application/json

form表單

form表單默認是urlencoded編碼格式傳輸數據
urlencoded數據格式:
    username=jason&password=123
    django後端針對該格式的數據 會自動解析並幫你打包到request.POST中

formdata數據格式:
    django後端針對符合urlencoded編碼格式數據(普通鍵值對)仍是統一解析到request.POST中
    而針對formdata文件數據就會自動解析放到request.FILES中
    
application/json
    django後端針對json格式數據 並不會作任何的處理
    而是直接放在request.body中

ajax提交

ajax默認的也是urlencoded編碼格式
    先後端數據交互 編碼格式與數據格式必定要一致
    不能騙人家!!! ,聲明什麼編碼格式,就用傳什麼格式
$('#d2').on('click',function () {
                $.ajax({
                    url:'',
                    type:'post',
                    contentType:'application/json',  // 修改content-Type參數
                    data:JSON.stringify({'username':'jason','password':123}),  // 將數據序列化成json格式字符串
                    success:function (data) {
                        alert(data)
                    }
                })
            })

1578658251513

後端怎麼拿json數據?

前端不會處理json格式的數據,而是直接塞進request.body中。咱們本身處理json格式數據,拿到的是二進制json

咱們本身怎麼拿?

咱們本身處理,解碼,反序列化

json.loads可以自動解碼而且序列化

def ab_ct(request):
    if request.method == 'POST':
        # 本身處理json格式數據
        json_bytes = request.body
        # 擴展 json.loads可以自動解碼並序列化
        json_dict = json.loads(json_bytes)
        print(json_dict,type(json_dict))
        print(request.POST)
        print(request.FILES)
    return render(request,'ab_ct.html')

AJAX發送文件

須要藉助內置對象FormData

這個對象能夠傳普通鍵值對,也能夠傳文件

jQ new關鍵字生成對象

ajax發送文件(******)
        內置對象FormData
        即發普通鍵值對也發文件
        // ajax發送文件數據  須要藉助於內置對象
        $('#d3').click(function () {
            // 1 須要先生成一個內置對象
            var myFormData = new FormData();
            // 2 傳普通鍵值對  當普通鍵值對較多的時候 咱們能夠利用for循環來添加
            myFormData.append('username','jason');
            myFormData.append('password',123);
            // 3 傳文件
            myFormData.append('myfile',$('#i1')[0].files[0]);  // 獲取input框內部用戶上傳的文件對象
            // 發送ajax請求
            $.ajax({
                url:'',
                type:'post',
                data:myFormData,
                // 發送formdata對象須要指定兩個關鍵性的參數

                processData:false,  // 讓瀏覽器不要對你的數據進行任何的操做
                contentType:false,  // 不要使用任何編碼格式 對象formdata自帶編碼格式而且django可以識別該對象

                success:function (data) {
                    alert(data)
                }
            })
        })

自動序列化

藉助serializers幫你自動完成序列化

from app01 import models
from django.core import serializers
def ab_se(request):
    user_queryset = models.Userinfo.objects.all()
    user_list = []
    for user_obj in user_queryset:
        user_list.append({
            'username':user_obj.username,
            'password':user_obj.password,
            'gender':user_obj.get_gender_display(),
        })
    res = json.dumps(user_list)
    res = serializers.serialize('json',user_queryset)  # 序列化
    return HttpResponse(res)

分頁器運用

須要大家掌握的僅僅是如何使用便可
    推導思路能夠稍做了解
    後端
        current_page = request.GET.get('page', 1)
        all_count = book_queryset.count()
        # 1 現生成一個自定義分頁器類對象
        page_obj = Pagination(current_page=current_page,all_count=all_count,pager_count=9)
        # 2 針對真實的queryset數據進行切片操做
        page_queryset = book_queryset[page_obj.start:page_obj.end]
        return render(request,'ab_bc.html',locals())

    前端  
        {% for book_obj in page_queryset %}
            <p>{{ book_obj.title }}</p>
        {% endfor %}
        {{ page_obj.page_html|safe }}

CV大法

class Pagination(object):
    def __init__(self,current_page,all_count,per_page_num=2,pager_count=11):
        """
        封裝分頁相關數據
        :param current_page: 當前頁
        :param all_count:    數據庫中的數據總條數
        :param per_page_num: 每頁顯示的數據條數
        :param pager_count:  最多顯示的頁碼個數
        
        用法:
        queryset = model.objects.all()
        page_obj = Pagination(current_page,all_count)
        page_data = queryset[page_obj.start:page_obj.end]
        獲取數據用page_data而再也不使用原始的queryset
        獲取前端分頁樣式用page_obj.page_html
        """
        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


        # 總頁碼
        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 = []
        # 添加前面的nav和ul標籤
        page_html_list.append('''
                    <nav aria-label='Page navigation>'
                    <ul class='pagination'>
                ''')
        first_page = '<li><a href="?page=%s">首頁</a></li>' % (1)
        page_html_list.append(first_page)

        if self.current_page <= 1:
            prev_page = '<li class="disabled"><a href="#">上一頁</a></li>'
        else:
            prev_page = '<li><a href="?page=%s">上一頁</a></li>' % (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="?page=%s">%s</a></li>' % (i, i,)
            else:
                temp = '<li><a href="?page=%s">%s</a></li>' % (i, i,)
            page_html_list.append(temp)

        if self.current_page >= self.all_pager:
            next_page = '<li class="disabled"><a href="#">下一頁</a></li>'
        else:
            next_page = '<li><a href="?page=%s">下一頁</a></li>' % (self.current_page + 1,)
        page_html_list.append(next_page)

        last_page = '<li><a href="?page=%s">尾頁</a></li>' % (self.all_pager,)
        page_html_list.append(last_page)
        # 尾部添加標籤
        page_html_list.append('''
                                           </nav>
                                           </ul>
                                       ''')
        return ''.join(page_html_list)
相關文章
相關標籤/搜索