使用AJAX和Django獲取數(shù)據(jù)的方法實(shí)例
前言
使用Django服務(wù)網(wǎng)頁(yè)時(shí),只要用戶執(zhí)行導(dǎo)致頁(yè)面更改的操作,即使該更改僅影響頁(yè)面的一小部分,它都會(huì)將完整的HTML模板傳遞給瀏覽器。 但是如果我們只想更新頁(yè)面的一部分,則不必完全重新渲染頁(yè)面-我們可以使用AJAX代替。
AJAX提供了一種將GET或POST請(qǐng)求發(fā)送到Django視圖并接收任何返回的數(shù)據(jù)而無(wú)需刷新頁(yè)面的方法。 現(xiàn)代JavaScript包含fetch API,該API為我們提供了一種純JavaScript方式來(lái)發(fā)送AJAX請(qǐng)求。
讓我們看一下如何通過(guò)獲取發(fā)出GET和POST請(qǐng)求,以在視圖和模板之間傳遞JSON數(shù)據(jù)。
GET請(qǐng)求
通過(guò)獲取發(fā)出GET請(qǐng)求
通過(guò)向其提供視圖的URL和適當(dāng)?shù)臉?biāo)頭來(lái)進(jìn)行帶有獲取的GET請(qǐng)求。 發(fā)出請(qǐng)求后,視圖返回請(qǐng)求的數(shù)據(jù),然后需要將響應(yīng)轉(zhuǎn)換為JSON,然后才能將其用于其他操作。
fetch(URL, {
headers:{
'Accept': 'application/json',
'X-Requested-With': 'XMLHttpRequest', //Necessary to work with request.is_ajax()
},
})
.then(response => {
return response.json() //Convert response to JSON
})
.then(data => {
//Perform actions with the response data from the view
})
URL
提取將URL作為其第一個(gè)參數(shù)。根據(jù)Django項(xiàng)目的URLconf和視圖的配置方式,URL可能包含關(guān)鍵字參數(shù)或查詢字符串,我們希望在視圖中使用該參數(shù)來(lái)選擇請(qǐng)求的數(shù)據(jù)。
Headers
通過(guò)提取進(jìn)行的AJAX請(qǐng)求將包含多個(gè)標(biāo)頭。我們希望數(shù)據(jù)以JSON形式從視圖返回,因此我們將'Accept'標(biāo)頭設(shè)置為'application / json'。在視圖中,我們可能要確保該請(qǐng)求是AJAX請(qǐng)求。通過(guò)將設(shè)置為“ XMLHttpRequest”的“ X-Requested-With”標(biāo)頭包括在內(nèi),該視圖將能夠檢查請(qǐng)求是否為AJAX。
提取不會(huì)直接返回?cái)?shù)據(jù)。相反,它將返回一個(gè)承諾,該承諾將被兌現(xiàn)并解決所請(qǐng)求的響應(yīng)。為了從響應(yīng)中獲取數(shù)據(jù),我們必須通過(guò)多次使用.then處理程序來(lái)使用鏈?zhǔn)匠兄Z。第一個(gè).then接收已解析的響應(yīng)并將其轉(zhuǎn)換為JSON。第二個(gè).then允許我們?cè)L問(wèn)第一個(gè).then返回的數(shù)據(jù),并允許我們使用它,但是我們想更新頁(yè)面。
在視圖中處理GET請(qǐng)求
我們需要一個(gè)視圖來(lái)處理來(lái)自fetch調(diào)用的AJAX請(qǐng)求。這可以通過(guò)多種方式完成,但是最簡(jiǎn)單的方法之一就是使用基于函數(shù)的視圖,該視圖接受請(qǐng)求并返回帶有請(qǐng)求數(shù)據(jù)的JsonResponse。
# views.py
from django.http import JsonResponse
def ajax_get_view(request): # May include more arguments depending on URL parameters
# Get data from the database - Ex. Model.object.get(...)
data = {
'my_data':data_to_display
}
return JsonResponse(data)
如果通過(guò)包含附加參數(shù)的URL訪問(wèn)該視圖,則這些附加參數(shù)也將與請(qǐng)求一起包含在功能參數(shù)列表中。 將根據(jù)那些URL參數(shù)或查詢字符串(如果使用的話)從數(shù)據(jù)庫(kù)中檢索數(shù)據(jù)。 我們要發(fā)送回頁(yè)面的數(shù)據(jù)必須在提供給JsonResponse的字典中。 調(diào)用之前,請(qǐng)確保從django.http導(dǎo)入JsonResponse。
該視圖將返回JsonResponse,該序列將數(shù)據(jù)字典序列化并將其發(fā)送回我們的頁(yè)面,在此頁(yè)面中將通過(guò)鏈接的promise進(jìn)行處理。 現(xiàn)在,我們可以使用JavaScript使用GET請(qǐng)求中的數(shù)據(jù)來(lái)更新頁(yè)面的一部分。
POST請(qǐng)求
通過(guò)提取發(fā)出POST請(qǐng)求
帶GET的POST請(qǐng)求比GET請(qǐng)求需要更多的參數(shù)。
fetch(URL, {
method: 'POST',
credentials: 'same-origin',
headers:{
'Accept': 'application/json',
'X-Requested-With': 'XMLHttpRequest', //Necessary to work with request.is_ajax()
'X-CSRFToken': csrftoken,
},
body: JSON.stringify({'post_data':'Data to post'}) //JavaScript object of data to POST
})
.then(response => {
return response.json() //Convert response to JSON
})
.then(data => {
//Perform actions with the response data from the view
})
Method
提取默認(rèn)為發(fā)出GET請(qǐng)求。我們必須通過(guò)添加方法“ POST”來(lái)明確地告訴它發(fā)出POST請(qǐng)求。
Credentials
我們需要指定如何在請(qǐng)求中發(fā)送憑據(jù)。憑證可能很棘手,特別是如果項(xiàng)目的前端和后端分別托管。如果AJAX請(qǐng)求是通過(guò)與后端其他位置相同的模板提供的,我們可以使用默認(rèn)值“ same-origin”。這意味著,如果所請(qǐng)求的URL與提取調(diào)用來(lái)自同一站點(diǎn),則將在請(qǐng)求中發(fā)送用戶憑據(jù)。如果前端和后端不在某個(gè)位置,則需要使用不同的憑據(jù)設(shè)置,并且需要考慮跨域資源共享(CORS)。
Headers
“ Accept”和“ X-Requested-With”標(biāo)頭與GET請(qǐng)求的標(biāo)頭相同,但是現(xiàn)在必須包括一個(gè)附加的“ X-CSRFToken”標(biāo)頭。
向Django發(fā)出POST請(qǐng)求時(shí),我們需要包含csrf令牌以防止跨站點(diǎn)請(qǐng)求偽造攻擊。 Django文檔提供了我們需要添加的確切JavaScript代碼,以從csrftoken cookie中獲取令牌。
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim();
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
const csrftoken = getCookie('csrftoken');
現(xiàn)在我們有了csrftoken,我們將其添加到標(biāo)頭中作為“ X-CSRFToken”:csrftoken。
BODY
POST請(qǐng)求的目標(biāo)是將數(shù)據(jù)發(fā)送到視圖并更新數(shù)據(jù)庫(kù)。 這意味著我們還需要在fetch調(diào)用中包含數(shù)據(jù)。 假設(shè)我們要發(fā)送JSON數(shù)據(jù),我們添加主體:JSON.stringify(data)其中data是我們要發(fā)送的數(shù)據(jù)的JavaScript對(duì)象。 除了JSON數(shù)據(jù)(包括文件和來(lái)自表單的數(shù)據(jù))外,其他數(shù)據(jù)也可以在正文中發(fā)送。 有關(guān)如何包含其他類型的數(shù)據(jù)的更多信息,請(qǐng)參見(jiàn)MDN文檔。
我們從POST請(qǐng)求中獲得的響應(yīng)將像GET請(qǐng)求一樣使用鏈?zhǔn)匠兄Z進(jìn)行處理。
在視圖中處理POST請(qǐng)求
接受POST請(qǐng)求的視圖將從請(qǐng)求中獲取數(shù)據(jù),對(duì)其執(zhí)行一些操作,然后返回響應(yīng)。
# views.py
from django.http import JsonResponse
import json
def ajax_post_view(request):
data_from_post = json.load(request)['post_data'] #Get data from POST request
#Do something with the data from the POST request
#If sending data back to the view, create the data dictionary
data = {
'my_data':data_to_display,
}
return JsonResponse(data)
我們認(rèn)為,我們需要從AJAX請(qǐng)求中提取數(shù)據(jù)才能使用它。數(shù)據(jù)以JSON格式發(fā)送,因此我們需要使用json.load(request)將其加載到視圖中。這需要從Python標(biāo)準(zhǔn)庫(kù)中導(dǎo)入json模塊。結(jié)果是我們通過(guò)提取發(fā)送的數(shù)據(jù)的字典?,F(xiàn)在,我們可以通過(guò)其鍵訪問(wèn)數(shù)據(jù)。
一旦獲得了請(qǐng)求中的數(shù)據(jù),我們就可以執(zhí)行用戶希望啟動(dòng)AJAX請(qǐng)求的操作。這可能是創(chuàng)建模型的新實(shí)例或更新現(xiàn)有實(shí)例。
與GET請(qǐng)求一樣,可以使用JsonResponse和帶有數(shù)據(jù)的字典將數(shù)據(jù)發(fā)送回頁(yè)面。這可以是新的或更新的模型對(duì)象,也可以是成功消息。
確保請(qǐng)求是AJAX
在大多數(shù)情況下,都會(huì)發(fā)出AJAX請(qǐng)求,因?yàn)槲覀冎幌M马?yè)面的一部分,并且需要獲取新數(shù)據(jù)來(lái)進(jìn)行更新。在頁(yè)面上下文之外,JsonResponse返回的數(shù)據(jù)本身很少使用。但是,如果我們沒(méi)有正確設(shè)置視圖,則可以在AJAX請(qǐng)求之外訪問(wèn)數(shù)據(jù),并且不會(huì)像我們期望的那樣將其呈現(xiàn)給用戶。
為了防止這種情況的發(fā)生,我們可以使用request.is_ajax()方法在視圖中添加檢查以確保該請(qǐng)求是AJAX請(qǐng)求。
# views.py
from django.http import JsonResponse
def ajax_view(request):
if request.is_ajax():
data = {
'my_data':data_to_display
}
return JsonResponse(data)
這使用“ X-Requested-With”標(biāo)頭來(lái)確定請(qǐng)求是否由AJAX發(fā)起。 如果嘗試通過(guò)直接在瀏覽器中鍵入U(xiǎn)RL來(lái)訪問(wèn)此視圖,則會(huì)收到錯(cuò)誤消息。 可以向視圖中添加其他邏輯(例如重定向),以防止用戶嘗試在沒(méi)有AJAX請(qǐng)求的情況下訪問(wèn)視圖時(shí)看到錯(cuò)誤。
Django 3.1及更高版本
在即將發(fā)布的Django 3.1版本(2020年8月)中,request.is_ajax()將被棄用。 這意味著如果我們要檢查AJAX請(qǐng)求,則必須自己重新創(chuàng)建功能。 幸運(yùn)的是,Django開(kāi)發(fā)人員確切地告訴我們我們需要做什么。 我們必須自己從request.is_ajax()方法重新創(chuàng)建邏輯,該邏輯只有1行代碼:
request.headers.get('x-requested-with') == 'XMLHttpRequest'
現(xiàn)在,我們可以編輯視圖以包括此檢查:
def ajax_view(request):
if request.headers.get('x-requested-with') == 'XMLHttpRequest':
# Get requested data and create data dictionary
return JsonResponse(data))
一些重要注意事項(xiàng)
盡管獲取是發(fā)出AJAX請(qǐng)求的便捷方法,但并非所有瀏覽器(即所有版本的Internet Explorer)都支持提取。 如果需要支持IE,請(qǐng)查看jQuery或XMLHttpRequest來(lái)發(fā)出AJAX請(qǐng)求。
AJAX請(qǐng)求應(yīng)僅限于Django項(xiàng)目的一小部分。 如果發(fā)現(xiàn)自己在多個(gè)模板中使用它們來(lái)獲取大量數(shù)據(jù),請(qǐng)考慮使用Django Rest Framework創(chuàng)建API。
概要
通過(guò)在Django項(xiàng)目中使用AJAX請(qǐng)求,我們可以更改頁(yè)面的某些部分而無(wú)需重新加載整個(gè)頁(yè)面。 提取API使添加此功能相當(dāng)輕松,同時(shí)需要最少的JavaScript。 正確而謹(jǐn)慎地使用它,可以使我們的頁(yè)面感覺(jué)更快,并為用戶提供更多的交互體驗(yàn)。
原文:https://www.brennantymrak.com/articles/fetching-data-with-ajax-and-django.html
總結(jié)
到此這篇關(guān)于使用AJAX和Django獲取數(shù)據(jù)的文章就介紹到這了,更多相關(guān)AJAX和Django獲取數(shù)據(jù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Pyinstaller打包報(bào)錯(cuò)小結(jié)
本文主要介紹了Pyinstaller打包報(bào)錯(cuò)小結(jié),詳細(xì)的介紹了5種錯(cuò)誤的解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-02-02
python數(shù)據(jù)庫(kù)操作--數(shù)據(jù)庫(kù)使用概述
這篇文章主要介紹了python中使用mysql數(shù)據(jù)庫(kù)詳細(xì)介紹,本文起講解了安裝mysql、安裝MySQL-python、mysql 的基本操作、python 操作mysql數(shù)據(jù)庫(kù)基礎(chǔ)等內(nèi)容,需要的朋友可以參考下2021-08-08
python在windows和linux下獲得本機(jī)本地ip地址方法小結(jié)
這篇文章主要介紹了python在windows和linux下獲得本機(jī)本地ip地址方法,實(shí)例分析了Python獲得IP地址的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-03-03
基于opencv實(shí)現(xiàn)手勢(shì)控制音量(案例詳解)
這篇文章主要介紹了基于opencv的手勢(shì)控制音量和ai換臉,通過(guò)定義了一個(gè)名為 handDetector 的類,用于檢測(cè)和跟蹤手部,結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-08-08
Pytest初學(xué)者快速上手高效Python測(cè)試指南
這篇文章主要為大家介紹了Pytest初學(xué)者快速上手的高效Python測(cè)試指南,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01
PyCharm接入DeepSeek實(shí)現(xiàn)AI編程的操作流程
DeepSeek 是一家專注于人工智能技術(shù)研發(fā)的公司,致力于開(kāi)發(fā)高性能、低成本的 AI 模型,接下來(lái),我們把DeepSeek接入到PyCharm中,并利用其能力輔助我們進(jìn)行代碼開(kāi)發(fā),感興趣的小伙伴跟著小編一起來(lái)看看吧2025-01-01
Django基礎(chǔ)知識(shí) web框架的本質(zhì)詳解
這篇文章主要介紹了Django基礎(chǔ)知識(shí) web框架的本質(zhì)詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-07-07

