Django學習 以後端視圖與ajax

.Ajax簡介

在此以前你必定須要先學習下JavaScript JSON 可見:html

前端學習 之 JavaScript 之 JSON前端

1、簡單介紹

咱們之前知道的前端向後端發送數據的方式有:jquery

  GET:地址欄、a標籤、Form表單ajax

  POST:Form表單chrome

那麼如今咱們在學習一種:那就是ajaxdjango

ajax:也是前端向後端發送數據的一種方式json

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

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

同步交互:客戶端發出一個請求後,須要等待服務器響應結束後,才能發出第二個請求;服務器

異步交互:客戶端發出一個請求後,無需等待服務器響應結束,就能夠發出第二個請求。

Ajax的特色(優勢)

  異步交互: 當請求發出後,瀏覽器還能夠進行其餘操做,無需等待服務器的響應!

  局部刷新:    整個過程當中頁面沒有刷新,只是刷新頁面中的局部位置而已!

二.jQuery實現Ajax

前提是在Django框架上,並已經作相關的基礎配置後。

前端代碼:

<body>
{% csrf_token %}
<p><input type="text" class="user" placeholder="用戶名"></p>
<p><input type="password" placeholder="密碼" class="pwd"></p>
<button id="ajaxTest">AJAX 測試</button>
 <script src="/static/js/jquery.js"></script>
<script>
    $("#ajaxTest").click(function () {
        var username = $(".user").val();
        var password = $(".pwd").val();
        console.log(username, password);
        $.ajax({
            url: "/jq_ajax/",
            type: "POST",
            data: {
                csrfmiddlewaretoken: $("input[name='csrfmiddlewaretoken']").val(),
                user: username,
                pwd: password,
            },
            success: function (res) {
                alert("hahaha")
                //將來接收服務端返回值,來進行作判斷作的相應的反應
                if (res == "ok"){
                    alert("okla")
                }else{
                    alert("buok.")
                }
            }
        })
    })
</script>
</body>
View Code

 

後端代碼:

def jq_ajax(request):

    # if request.method == "GET":

 

    if request.is_ajax():

        username = request.POST.get("user")

        password = request.POST.get("pwd")

        print(username, password)

        return HttpResponse("okddd")

 

return render(request, "jq_ajax.html")
views.py

.Ajax案例

1.用戶名是否已被註冊

在註冊表單中,當用戶填寫了用戶名後,把光標移開後,會自動向服務器發送異步請求。服務器返回true或false,返回true表示這個用戶名已經被註冊過,返回false表示沒有註冊過。客戶端獲得服務器返回的結果後,肯定是否在用戶名文本框後顯示「用戶名已被註冊」的錯誤信息!

2.基於Ajax進行登陸驗證

用戶在表單輸入要註冊用戶名,用戶單擊框外,網頁經過Ajax提交給服務器,服務器驗證用戶名是否存在後返回響應信息,客戶端經過響應信息作出相應的提醒,能夠註冊不提醒,不然在頁面上顯示登陸用戶名已經被使用!

.Ajax實現一個計算案例

前端代碼爲:

<body>

<h3>計算案例</h3>

{% csrf_token %}

<input type="text" id="i1"> + <input type="text" id="i2"> = <input type="text" id="i3"> <button id="btn1">計算</button>

<span id="err"></span>

<script src="/static/js/jquery.js"></script>

<script>

    $("#btn1").click(function () {

        var i1 = $("#i1").val()

        var i2 = $("#i2").val()

        $.ajax(

            {

                url:"/add_test/",

                type: "post",

                data:{

                    csrfmiddlewaretoken: $("input[name='csrfmiddlewaretoken']").val(),

                    i1:i1,

                    i2:i2,

                },

                success : function (ret) {

                    {#var ret = JSON.parse(ret);   //在django後端用的是JsonResponse就不用反序列化了#}

                    console.log(ret,typeof ret);

                    if (ret.status){

                        $("#i3").val(ret.msg);

                    }else {

                        $("#err").text(ret.msg);

                        // 過三秒後自動消失

                        setTimeout(function () {

                            $("#err").text("");

                        },3000)

                    }

                    {#$("#i3").val(res)#}

                }

            }

        )

 

    })

</script>

</body>

 

後端django視圖函數爲:

from django.http import JsonResponse

import json

def add_test(request):

    if request.is_ajax():

        ret = {"status": 1, "msg": None}

        num1 = request.POST.get("i1")

        num2 = request.POST.get("i2")

        try:

 

            res = int(num1) + int(num2)

            ret['msg'] = res

        except ValueError as e:

            ret['status'] = 0

            ret['msg'] = "請覈對輸入的數據的合法性"

 

        # return HttpResponse(json.dumps(ret))  

//若是用到 JsonResponse就不須要序列化了

        return JsonResponse(ret)

    return render(request, "add_test.html")

.基於Ajax上傳json數據

1.前端模板代碼

<body>

{% csrf_token %}

<h3>json 數據</h3>

<p><input type="text" class="user" placeholder="用戶名"></p>

<p><input type="password" placeholder="密碼" class="pwd"></p>

<button id="ajaxTest">AJAX json 測試</button>

 

<script src="/static/js/jquery.js"></script>

<script>

        $("#ajaxTest").click(function () {

        var user = $(".user").val();

        var pwd = $('.pwd').val();

        $.ajax({

            url: "",

            type: 'POST',

            //注意T大寫

            contentType: "json",

            headers: {"X-CSRFToken": $("input[name='csrfmiddlewaretoken']").val()}, // 在請求頭中添加csrf

            // json 前端的序列化方式

            data: JSON.stringify({

                user: user,

                pwd: pwd,

                {#csrfmiddlewaretoken: $("input[name='csrfmiddlewaretoken']").val(),#}

            }),

            success: function (ret) {

                console.log(ret)

            }

        })

    })

</script>

</body>

 

2.後端視圖代碼

def json_test(request):

    if request.is_ajax():

        print(request.POST)  # json時,post爲空

        print(request.body)  # 若是前端沒有序列化就是原生請求體內容,若是序列化的就是字典(實際上是byte類型)

        data_str = request.body.decode()

        data = json.loads(data_str)

        print(data, type(data))  # 是字典類型

        # print(data.get('user'), type(data))

        return HttpResponse("ok")

return render(request, "json_test.html")

 

總結:

前端:

    $.ajax({

        url: "", # 默認往當前url提交

        type: "post", #請求方式

        contentType: "json",

        headers: {"X-CSRFToken": $("input[name='csrfmiddlewaretoken']").val()}, // 在請求頭中添加csrf

        data: JSON.stringify({

         key1: val1,

            key2: val2,

            ...

        },

            success: function(ret){

                console.log(ret)

            }

    })

 

後端:

    request.POST     # 爲空

    request.body    # b'{"user":"alex","pwd":"123"}'

        1. 轉換成字符串

        2. 反序列化  # dict1 = json.loads(request.body.decode())

.基於form表單上傳文件

1.前端模板代碼

<body>

<h3>文件上傳</h3>

<form action="" method="post" enctype="multipart/form-data">

    {% csrf_token %}

    <input type="file" name="f_name">

    <input type="submit" value="上傳">

</form>

</body>
View Code

 

2.後端視圖代碼

import os

def upload(request):

    if request.method == "GET":

        return render(request, 'upload.html')

    else:

        print(request.POST)   # <class 'str'> 沒有意義

        # print(request.body) #  enctype="multipart/form-data"   ,會報錯

        print(request.FILES.get('f_name'), type(request.FILES.get('f_name')))

# 類型是一個對象

        file_obj = request.FILES.get('f_name')

        print(file_obj.name)

        with open(os.path.join("media",file_obj.name),mode="wb") as fp:

            for i in file_obj:

                fp.write(i)

 

        return HttpResponse("ok")

 

 .基於Ajax請求上傳文件

1.前端模板代碼

<body>

<h3>ajax 文件上傳</h3>

    {% csrf_token %}

    <input type="file" id="file_id">

    <input type="button" value="上傳" id="btn1">

 

<script src="/static/js/jquery.js"></script>

<script>

    $("#btn1").click(function () {

        // 封裝數據

        let formdata = new FormData();

        formdata.append("csrfmiddlewaretoken", $("[name='csrfmiddlewaretoken']").val());

        // f_name 傳到後端當字典的鍵,另一個則是一個對象

        formdata.append('f_name', $("#file_id")[0].files[0]);

        // 處理ajax請求

        $.ajax({

            url: "",

            type: "POST",

            processData: false,  // 告訴jQuery不要去處理髮送的數據

            contentType: false,  // 告訴jQuery不要去設置Content-Type請求頭

            data: formdata,

            // 成功後返回的數據

            success: function (ret) {

                console.log(ret)

            }

 

        })

    })

</script>

</body>

 

獲取頁面的文件對象步驟:

 

2.後端視圖代碼

def upload_ajax(request):

    if request.method == "GET":

        return render(request, "upload_ajax.html")

    else:

        print(request.POST)

        # print(type(request.POST.get("fi_name1")))  #<class 'str'> 沒有意義

        # print(request.body)   #  enctype="multipart/form-data"   ,會報錯

        print(request.FILES)

        print(request.FILES.get('f_name'))

        print(type(request.FILES.get('f_name')))

        file_obj = request.FILES.get('f_name')

        print(file_obj.name)

 

        with open(os.path.join("media", file_obj.name), "wb") as f:

            for i in file_obj:

                f.write(i)

 

        return HttpResponse("ok")

 

後端視圖代碼基本和基礎表單上傳文件的同樣。

.ContentType 類型

ContentType指的是請求體的編碼類型,常見的類型共有3種:

1.application/x-www-form-urlencoded(默認類型)

    這應該是最多見的 POST 提交數據的方式了。瀏覽器的原生 <form> 表單,若是不設置 enctype 屬性,那麼最終就會以 application/x-www-form-urlencoded 方式提交數據。請求相似於下面這樣(無關的請求頭在本文中都省略掉了):

POST http://www.example.com HTTP/1.1

Content-Type: application/x-www-form-urlencoded;charset=utf-8

 

user=hsz&age=22

 

2.multipart/form-data(用於form上傳文件時)

這又是一個常見的 POST 數據提交的方式。咱們使用表單上傳文件時,必須讓 <form> 表單的 enctype 等於 multipart/form-data。直接來看一個請求示例:

POST http://www.example.com HTTP/1.1

Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA

 

------WebKitFormBoundaryrGKCBY7qhFd3TrwA

Content-Disposition: form-data; name="user"

 

hsz

------WebKitFormBoundaryrGKCBY7qhFd3TrwA

Content-Disposition: form-data; name="file"; filename="chrome.png"

Content-Type: image/png

 

PNG ... content of chrome.png ...

------WebKitFormBoundaryrGKCBY7qhFd3TrwA--

 

 

這個例子稍微複雜點。首先生成了一個 boundary 用於分割不一樣的字段,爲了不與正文內容重複,boundary 很長很複雜。而後 Content-Type 裏指明瞭數據是以 multipart/form-data 來編碼,本次請求的 boundary 是什麼內容。消息主體裏按照字段個數又分爲多個結構相似的部分,每部分都是以 --boundary 開始,緊接着是內容描述信息,而後是回車,最後是字段具體內容(文本或二進制)。若是傳輸的是文件,還要包含文件名和文件類型信息。消息主體最後以 --boundary-- 標示結束。關於 multipart/form-data 的詳細定義,請前往 rfc1867 查看。

    這種方式通常用來上傳文件,各大服務端語言對它也有着良好的支持。

    上面提到的這兩種 POST 數據的方式,都是瀏覽器原生支持的,並且現階段標準中原生 <form> 表單也只支持這兩種方式(經過 <form> 元素的 enctype 屬性指定,默認爲 application/x-www-form-urlencoded。其實 enctype 還支持 text/plain,不過用得很是少)。

隨着愈來愈多的 Web 站點,尤爲是 WebApp,所有使用 Ajax 進行數據交互以後,咱們徹底能夠定義新的數據提交方式,給開發帶來更多便利。

3.application/json(用於json)

application/json 這個 Content-Type 做爲響應頭你們確定不陌生。實際上,如今愈來愈多的人把它做爲請求頭,用來告訴服務端消息主體是序列化後的 JSON 字符串。因爲 JSON 規範的流行,除了低版本 IE 以外的各大瀏覽器都原生支持 JSON.stringify,服務端語言也都有處理 JSON 的函數,使用 JSON 不會趕上什麼麻煩。

    JSON 格式支持比鍵值對複雜得多的結構化數據,這一點也頗有用。記得我幾年前作一個項目時,須要提交的數據層次很是深,我就是把數據 JSON 序列化以後來提交的。不過當時我是把 JSON 字符串做爲 val,仍然放在鍵值對裏,以 x-www-form-urlencoded 方式提交。

相關文章
相關標籤/搜索