Django之Ajax傳輸數據


MTV與MVC模型

MTV與MVC都是模型,只不過MTV是django自己定義的,具體看一下他們的意思

MTV模型(django)

M:模型層(models.py)

T:templates文件夾

V:視圖層(views)

MVC模型

M:模型層

V:視圖層(views.py)

C:控制器(Controller) urls.py

總結:本質上django的MTV也是MVC

前后端傳輸數據編碼格式

首先,在我們不指定傳輸數據的時候,默認的contentType都是urlencoded

urlencoded

  對應的數據格式:name=jason&password=555

  后端獲取數據:request.POST  

  PS:django會將urlencded編碼的數據解析自動放到request.POST

formdata

  form表單傳輸文件的編碼格式

  后端獲取文件格式數據:request.FILES

  后端獲取普通鍵值對數據:request.POST

application/json 

  form表單不支持,Ajax支持

  Ajax發送json格式數據

  需要注意的點

    編碼與數據格式要一致

 

Ajax(重點掌握)

 

Ajax支持異步提交數據,局部刷新頁面,這種情況我們在好多頁面都會看到,那我們要如何做到呢?先來學習Ajax的基礎語法~~~記住四兄弟即可

 

提交的地址(url):控制數據的提交地址,不寫默認往當前位置提交

 

提交的方式(type):默認是get,要將get請求換成post

 

提交的數據(data):類似於字典的格式,字典具有一一標識的優點

 

回調函數(success):function(data){}data接收到的后端傳輸的數據

 

基本結構如下:

 

<script>  //記得寫在html頁面的最下方或者是你寫在js里面,然后引入
    $('綁定事件的id').click(function () {   //給你要讓Ajax觸發的按鈕綁定一個事件
        $.ajax({                          //Ajax的固定寫法,在{}里面寫你的四兄弟
            url:'在這里寫你的提交的路徑',     //不寫默認是當前頁面提交
            type:'post' ,                 //將請求方式從默認的get改成post
            data:{},                      //這個固定是data,后面放的是字典的形式
            success:function (data) {     //回調函數,拿到的是提交過后的數據,就是后端處理過后的數據,不要忘記參數,這個參數就是接收后端處理過后的數據
                //對接受到的數據進行處理,做的是局部刷新操作
          alert(123)
} }) }) </script>

 

自己嘗試着寫一個不跳轉的動態頁面,比如1+1=2

Ajax實現簡單版頁面局部刷新

我們首先需要的就是自己定義三個input框,然后動態獲取到前兩個框中的值,通過Ajax放到第三個input框中,代碼演示如下

<input type="text" id="i1" >+<input type="text" id="i2" >=<input type="text" id="i3">
<button id="b1">點我點我</button>


<script>
$('#b1').click(function () {
    $.ajax({
        url:'/index/',
        type:'post',
        data:{'i1':$('#i1').val(),'i2':$('#i2').val()},
        success:function (data) {
            
            $('#i3').val(data)

        }
    })
})
</script>
html展示

后端數據處理

def index(request):
    if request.method=='POST':
        i1=request.POST.get('i1')
        i2=request.POST.get('i2')
        print(i1,i2)
        res=int(i1)+int(i2)
        print(res,type(res))
        return HttpResponse(res)
    return render(request,'index.html')
views展示

注意:Ajax不要與form表單聯合使用,直接使用input框就可以

Ajax實現json格式數據的傳輸

 

具體代碼展示如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">
    <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
</head>
<body>
<p>username:<input type="text" id="u1"></p>
<p>password:<input type="password" id="p1"></p>
<button id="b1">提交</button>
<input type="text" id="i1">

<script>
    $('#b1').click(function () {
        $.ajax({
            url:'',
            type:'post',
            contentType:'application/json',
            data:JSON.stringify({
                'username':$('#u1').val(),
                'password':$('#p1').val()
            }),
            success:function (data) {
                $('#i1').val(data)

            }
        })
    })
</script>


</body>
</html>
json格式html展示
def jsonajax(request):
    print('method:', request.method)
    print('POST:', request.POST)
    print('GET:', request.GET)
    print('body:', request.body)
    if request.method=='POST':
        data=request.body
        import json
        res=data.decode('utf-8')
        print(res,type(res))
        res1=json.loads(res)
        print(res1,type(res1))
        return HttpResponse(res1)
    return render(request,'jsonajax.html')
views展示

Ajax實現文件上傳

  1.利用一個js內置對象FormData

  2.這個FormData即可以傳普通的鍵值對也可以傳文件

  3.需要修改兩個默認的參數processData,contentType

  4.獲取input框存儲的文件數據$('input')[0].files[0]

def fileupload(request):

    if request.method=='POST':
        print(request.POST)
        print(request.FILES)

        return HttpResponse('收到了,小老弟')
    return render(request,'fileupload.html')
Ajax實現文件上傳views展示
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">
    <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
</head>
<body>
文件上傳:<input type="file" id="i1">
<button id="b1">點擊提交</button>
<script>
    $('#b1').click(function () {
       //傳文件的時候在form表單中我們需要制定參數是formdata,在這里我們也要來一個formdata
        let formdata = new FormData();
        // formData對象不僅可以傳文件而且可以傳普通的鍵值對
        formdata.append('name','jason');
        //獲取input框存放的文件
        //這里就用到了files這個方法,jquery是沒有這個方法的,所以我們要先得到一個js對象
        //$('#i1')[0].files[0]  是因為files里面有好多個文件,而我們只要第一個
        formdata.append('myfile',$('#i1')[0].files[0]);
        $.ajax({
           url:'',
           type:'post',
           data:formdata,
           //ajax發送文件需要修改兩個固定的參數
           processData:false,  //告訴瀏覽器不要對數據進行處理
           contentType:false,  //告訴瀏覽器使用自帶的formdata格式,不要編碼
           //回調函數
           success:function (data) {
               alert(data)
           }

        })
    })
</script>
</body>
</html>
Ajax實現文件上傳html展示

總結:Ajax的特點是異步提交數據,產生局部刷新的效果,默認提交數據的方式是get提交,所以我們需要修改里面的type類型,然后我們還可以自定義FormData對象,Ajax也支持基於這個對象的大文件上傳。

Ajax和form表單的區別:

1.form表單不支持異步提交局部刷新

2.form表單不支持傳輸json格式數據

3.form表單與Ajax默認傳輸數據的編碼格式都是urlencoded

 

 

小結:基於現在所學,前端向后端發請求的方式有如下幾種

1.瀏覽器窗口手動輸入網址     get請求

2.a標簽的href屬性                  get請求

3.form表單                              get/post請求

4.Ajax                                     get/post請求

其中,form表單和Ajax默認請求都是get

批量插入數據

當你打開一個頁面的時候,想要直接插入100條數據到數據庫,然后直接展示到前端頁面上來,如何做到?那還不簡單,我可以直接for循環100條數據,然后插入數據庫,最后在從數據庫中查出來展示,上代碼!

def insernum(request):
    #動態插入100條數據
    for i in range(100):
        models.Num.objects.create(name='第%s本書'%i)
    #查詢所有的書籍展示到前端
    book_list = models.Num.objects.all()
    return render(request,'num.html',locals())

但是,我們這樣子做到話,效果真的超級超級的低,前端頁面一直在等待我們數據的插入,雖然實現了數據的插入和展示,但是效率太低,那我們就得用到一個新的方法,我們先生成1000個數據對象,不走數據庫,速度是很快的,然后將這1000個數據對象一次性插入,django支持我們這么做,用的是bulk_creat(),批量插入數據,見代碼

def booklist(request):
    l=[]  #數據太大的話,能不能做成生成器,每次只有一點****
    for i in range(10000):
        l.append(models.Book2(name='第%s本書'%i))  生成了一個對象
    models.Book2.objects.bulk_create(l)  批量插入數據,速度超級快

  
  g=(=models.Book2(name = '%s'%i)for i in range(100000000))***
  
  models.Book2.objects.bulk_create(l)

 

自定義分頁器

首先我們要先導入一個類,這個類可以幫我們實現分頁的功能,將這個導入的文件放在utils里面,在下面新建一個py文件,你得給人家一個家不是嗎!

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)
分頁器

然后我們直接導入使用就可以了

    后端:
            book_list = models.Book2.objects.all()
            # 數據總條數
            all_count = book_list.count()
            # 當前頁
            current_page = request.GET.get('page',1)
            # 實例一個分頁器對象
            page_obj = my_page.Pagination(current_page=current_page,all_count=all_count)
            # 對總數據進行切片
            page_queryset = book_list[page_obj.start:page_obj.end]
        
        前端:
1.將book_list全部替換冊灰姑娘book_queryset    
       2.渲染分頁器樣式
{{ page_obj.page_html
|safe }} # 幫你渲染的是帶有bootstrap樣式的分頁器

django 自帶的分頁器,和我們差不多,就相當於每次手動寫一遍

 

又是一個愉快的周末🙂🙂🙂

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM