1. 程式人生 > >Django:(4)Django和Ajax

Django:(4)Django和Ajax

== login F5 地址欄 分享圖片 var 交互 val world

向服務器發送請求的途徑:

1. 瀏覽器地址欄,默認get請求

2. form表單:

  get請求;

  post請求

3. a標簽,默認get請求

4. Ajax:get請求;post請求

  Ajax的特點(記住):

    (1) 異步請求

    (2)局部刷新

AJAXAsynchronous Javascript And XML)翻譯成中文就是異步JavascriptXML”。即使用Javascript語言與服務器進行異步交互,傳輸的數據為XML(傳輸的數據不只是XML,現在更多使用json數據)。

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

優點:

  • AJAX使用Javascript技術向服務器發送異步請求
  • AJAX無須刷新整個頁面

基於Jquery的Ajax實現

目錄結構:

技術分享圖片

urls.py

from django.contrib import admin
from django.urls import path

from app01 import views

urlpatterns = [
    path(admin/, admin.site.urls),
    path(r"index/",views.index),
    path(r
"test_ajax/",views.test_ajax) # ajax的路徑需要有流程線(如,路由分發的路徑,視圖函數,頁面等) ]

views.py

from django.shortcuts import render,HttpResponse

# Create your views here.

def index(request):

    return render(request,"index.html")

def test_ajax(request):
    return HttpResponse("hello world")

index.html

<!DOCTYPE html
> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> </head> <body> <h2>this is Index</h2> <button class="ajax">Ajax</button> <p class="content"></p> </body> <script> $(".ajax").click(function () { $.ajax({ {# ajax請求的url;IP的端口沒寫就默認為當前的 #} url:"/test_ajax/", {# 請求方式;默認get #} type:"get", {#回調函數#} success:function (data) { $(".content").html(data) } }) }) {# 上述Ajax流程:點擊button按鈕,通過ajax向 特定的url發送請求;服務器返回字符串 "hello world"並傳給回調函數的形參 data;回調函數決定怎麽在頁面上展示data #} </script> </html>

Ajax傳遞數據:通過 data:{ } 的形式 發送數據

urls.py

from django.contrib import admin
from django.urls import path

from app01 import views

urlpatterns = [
    path(admin/, admin.site.urls),
    path(r"index/",views.index),
    path(r"plus/",views.plus)
]

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>

<input type="text" class="val1">+<input type="text" class="val2">=<input type="text" class="val3"> <button class="cal">計算</button>

</body>
<script>

$(".cal").click(function () {
    $.ajax({
        url:"/plus/",
        type:"post",
        {#ajax的input中不需要添加 name 屬性,只需要 class或id 能找到它就行;但form表單需要利用 name屬性去取值#}
        data:{
            {# input框中的值是字符串格式 #}
            "val1":$(".val1").val(),
            "val2":$(".val2").val()
        },
        success:function (data) {
            $(".val3").val(data)
        }
    })
})


</script>
</html>

views.py

from django.shortcuts import render,HttpResponse

def plus(request):
    print(request.POST)
    val1 = request.POST.get("val1")
    val2 = request.POST.get("val2")

    val3 = int(val1) + int(val2)

    return HttpResponse(val3)

註:settings.py MIDDLEWARE 中的 ‘django.middleware.csrf.CsrfViewMiddleware‘ 需要註釋掉

基於Ajax的登陸驗證(跨語言的Json)

目錄結構同上;settings.py 也註釋掉 csrf

urls.py

from django.contrib import admin
from django.urls import path

from app01 import views

urlpatterns = [
    path(admin/, admin.site.urls),
    path(r"index/",views.index),
    
    path(r"login/",views.login)
]

views.py

from django.shortcuts import render,HttpResponse

from app01.models import User

def login(request):
    print(request.POST)
    user = request.POST.get("user")
    psw = request.POST.get("psw")

    user_obj = User.objects.filter(name=user,psw=psw).first()
    res = {"user":None,"msg":None}

    if user_obj:  # 能在數據庫中匹配出來
        res["user"] = user_obj.name
    else:
        res["msg"] = "用戶名密碼錯誤"

    # 字典格式的數據類型不能直接發送,需要先轉化為字符串格式
    import json
    # 利用json.dumps()序列化
    return HttpResponse(json.dumps(res))

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>

{#form表單的action也沒必要寫,其實form標簽也沒必要;只是習慣上把form控件標簽放到form中#}
<form>
    用戶名 <input type="text" class="user">
    密碼 <input type="password" class="psw">
    {# 用ajax發請求時 input的type用"button",不要用"submit",否則就變成了form表單發送請求 #}
    <input type="button" value="submit" class="login_btn"><span class="error"></span>
</form>

</body>
<script>

{# 登陸驗證 #}
$(".login_btn").click(function () {
    {# 把ajax內置在某個事件中 #}
    $.ajax({
        url:"/login/",
        type:"post",
        data:{
            "user":$(".user").val(),
            "psw":$(".psw").val()
        },
        success:function (data) {
            console.log(data)
            {# 此時data為json字符串格式 #}
            console.log(typeof data)

            {# 此時data這個字符串交給JS去處理了;就需要用JS的反序列化方法 #}
            {# 只要該語言支持json接口,它就能反解成自己支持的數據類型:python的字典會反解成JS的對象({}),python的列表會反解成JS的數組([])#}
            {# JSON.parse()是JS的反序列化方法 #}
            var new_data = JSON.parse(data)
            console.log(new_data)
            console.log(typeof new_data)

            if (new_data.user){
                {# location.href= 表示前端跳轉 #}
                location.href="https://www.baidu.com"
            }else {
                $(".error").html(new_data.msg).css({"color":"red","margin-left":"10px"})
            }

        }
    })
})


</script>
</html>

文件上傳:

請求頭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=yuan&age=22

  2. multipart/form-datamultipart/form-data:這又是一個常見的 POST 數據提交的方式。我們使用表單上傳文件時,必須讓 <form> 表單的 enctype 等於 multipart/form-data

  3. application/json:Json格式的字符串作為請求頭

基於form表單的文件上傳

urls.py

from django.contrib import admin
from django.urls import path

from app01 import views

urlpatterns = [
    path(r"file_put/",views.file_put)
]

views.py

from django.shortcuts import render,HttpResponse

def file_put(request):
    if request.method == "POST":


        # 1. 基於form表單的文件上傳
        print(request.POST)
        # request.POST 只有在 contentType = urlencoded 時候才有數據

        # 註意:上傳成功的文件放在 request.FILEs 這個屬性裏面
        print(request.FILES)

        # 下載所上傳的文件
        file_obj = request.FILES.get("avatar")
        # 文件對象有一個屬性 .name 表示文件名
        with open(file_obj.name,"wb") as f:
            for line in file_obj:
                f.write(line)
        
        return HttpResponse("ok")

    return render(request,"file_put.html")

file_put.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>

</head>
<body>
<h3>基於form表單的文件上傳</h3>

 註意:上傳文件的form表單中要寫上 enctype="multipart/form-data" 
<form action="" method="post" enctype="multipart/form-data">
    用戶名 <input type="text" name="user">
     上傳文件 input的type屬性值是 "file" 
    頭像 <input type="file" name="avatar">
    <input type="submit">

</script>
</html>

利用Ajax上傳普通數據

views.py

from django.shortcuts import render,HttpResponse

def file_put(request):
    if request.method == "POST":
        
        return HttpResponse("ok")

    return render(request,"file_put.html")

file_put.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>

</head>
<body>


<h3>基於Ajax的文件上傳</h3>

{# 利用Ajax上傳普通數據  #}
<form action="" method="post">
    用戶名 <input type="text" name="user">
    <input type="button" class="btn" value="Ajax">
</form>

</body>
<script>
    {#利用Ajax上傳普通數據  #}
    $(".btn").click(function () {
        $.ajax({
            {#url不寫默認為當前路徑#}
            url: "",
            type: "post",
            {#不指定enctype,默認用application/x-www-form-urlencoded #}
            data: {
                a: 1,
                b: 2
            },
            success: function (data) {
                console.log(data)
            }
        })
    })
 {#不論是form表單還是Ajax都有一個默認的請求頭 application/x-www-form-urlencoded  #}

</script>
</html>

Ajax傳遞Json數據

views.py

from django.shortcuts import render,HttpResponse

def file_put(request):
    if request.method == "POST":
         # 3. Ajax傳遞Json數據
        print("request.body",request.body)   # request.body:請求報文中的請求體(請求體的源數據);
        # request.body b‘{"a":1,"b":2}‘   # 此數據可通過python的json.dumps()方法獲取
        print("request.POST",request.POST)  # 此時 request.POST 中沒有數據
        # request.POST <QueryDict: {}>
    
         return HttpResponse("ok")

    return render(request,"file_put.html")

file_put.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>

</head>
<body>
{#Ajax傳遞Json數據#}
<form action="" method="post">
    用戶名 <input type="text" name="user">
    <input type="button" class="btn" value="Ajax">
</form>
</body>
<script>

{#Ajax傳遞Json數據#}
$(".btn").click(function () {
        $.ajax({
            {#url不寫默認為當前路徑#}
            url:"",
            type:"post",
            {#告訴服務器編碼類型為json數據#}
            contentType:"application/json",
             {#然後需要用JS的方法把數據變成Json數據類型:JSON.stringify():序列化 #}
             {#然後請求體中的數據就是 {"a":"1","b":"2"} 類型的json字符串 #}
            data:JSON.stringify({
                a:1,
                b:2
            }),
            success:function (data) {
                console.log(data)
            }
        })
    })

</script>
</html>

基於Ajax的文件上傳

from django.shortcuts import render,HttpResponse

def file_put(request):
    if request.method == "POST":
        # 4. 基於Ajax的文件上傳
        print("request.body", request.body)
        print("request.POST", request.POST)
        print(request.FILES)


        # 下載所上傳的文件
        file_obj = request.FILES.get("avatar")
        # file_obj = request.FILES.get("avatar")
        # 文件對象有一個屬性 .name 表示文件名
        with open(file_obj.name,"wb") as f:
            for line in file_obj:
                f.write(line)

        return HttpResponse("ok")

    return render(request,"file_put.html")

file_put.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>

</head>
<body>

{# 基於Ajax的文件上傳 #}
<form action="" method="post">
    用戶名 <input type="text" class="user">
     上傳文件 input的type屬性值是 "file"
    頭像 <input type="file" class="avatar">
    <input type="button" class="btn" value="Ajax">
</form>


</body>
<script>

{#  基於Ajax的文件上傳  #}
    $(".btn").click(function () {
         {#涉及到文件上傳,一定要用 FormData 創建一個新的對象(formdata編碼);固定格式 #}
        var formdata = new FormData();
        {#然後給創建的 formdata對象添加鍵值:append(key,value)方法 #}
        formdata.append("user",$(".user").val());
        formdata.append("avatar",$(".avatar")[0].files[0]);
         {#$(".avatar")[0]是對應的 input 標簽,DOM元素;取DOM元素中包含的文件對象: .files[0],固定語法 #}

        $.ajax({
            {#url不寫默認為當前路徑#}
            url:"",
            type:"post",
            {#傳formdata的時候一定要加上 contentType:false,processData:false, 這兩句代碼 #}
            {# contentType:false  表示不做編碼處理 #}
            contentType:false,
            {#processData:false表示不對數據做預處理#}
            processData:false,
            {#把formdata賦值給data#}
            data:formdata,
            success:function (data) {
                console.log(data)
            }
        })
    })

</script>
</html>

Django:(4)Django和Ajax