Django接口開發
一、前后端分離
- 傳統開發模式
url -->> 視圖函數(邏輯判斷、調用數據庫、渲染HTML)-->>向瀏覽器返回HTML頁面。
項目后台的商品列表頁面已經使用傳統開發模式實現了
但是呢,有時候我們需要將這些內容在移動端(手機APP)或者的設備上顯示。那怎么辦呢?
我們可以再編寫一套后台邏輯給移動端使用。但是這樣比較麻煩,工作量比較大。有沒有更簡單的方式呢?我們可以使用前后端分離開發模式
二、前后端分離模型
前后端分離模型指的是后端只負責返回數據,不再負責渲染頁面。前端負責渲染數據
接下來就要探討一下返回的數據類型,如果我們返回Python中的字典或者列表,但是前端人員或者移動端人員不一定會Python語法。我們可以返回一種前端人員、后台人員都會的一種數據類型,這樣就可以順利的完成開發了。一般在開發中我們返回JSON或者XML數據類型
三、JSON和XML
-
JSON介紹
JSON(JavaScript Object Notation) : 是一種輕量級的數據交換格式,JSON數據格式類似於Python中的字典
-
XML介紹
XML(Extensible Markup Language): 可擴展標記語言,很少企業使用XML進行數據傳輸,了解即可
-
JsonResponse
form django.http import JsonResponse
使用JsonResponse對象可以將Python中的字典或者其他數據類型轉換為JSON數據
# 路由 urlpatterns += [ # 查詢所有商品 path('api/goodses/', api_view.select_all_goods), # 視圖 def select_all_goods(request): """查詢所有的商品""" # 查詢所有商品得到的是QuerySet類型的對象 goods_qs = Goods.objects.all() # 轉成列表字典格式 goods_list = [{"id": goods.id, "name": goods.name} for goods in goods_qs] # JsonResponse return JsonResponse(goods_list,safe=False,json_dumps_params= {"ensure_ascii":False})
safe=False可以使用列表,默認只轉換字典格式
son_dumps_params={"ensure_ascii":False}:顯示中文
四、AJAX
-
AJAX介紹
AJAX(Asynchronous Javascript And XML)翻譯成中文就是“異步JavaScript和XML”。即使用JavaScript語言與服務器進行異步交互,傳輸的數據為XML(當然,傳輸的數據不只是XML)還有JSON數據
AJAX還有一個最大的特點就是,當服務器響應時,不用刷新整個瀏覽器頁面,而是可以局部刷新,這一特點給用戶的感受是在不知不覺中完成請求和響應過程
應用場景:注冊時信息校驗(百度首頁注冊) -
AJAX格式
使用原生的JavaScript 使用AJAX 比較麻煩,我們采用 jQuery 實現 AJAX 請求。
1、語法:$.ajax({參數1:值1,參數2,值2})- 參數介紹
參數 描述 url 發送請求的地址 type 請求方式("POST" 或 "GET"), 默認為 "GET"。注意:其它 HTTP 請求方法如 PUT 和 DELETE 也可以使用,但僅部分瀏覽器支持 data 發送到服務器的數據。格式 {key:value,key:value} error 請求失敗時調用此函數 success 請求成功后的回調函數,參數:由服務器返回數據 dataType 預期服務器返回的數據類型。如果不指定,瀏覽器會智能判斷
可用值:
"xml": 返回 XML 文檔,可用 jQuery 處理。
"html": 返回純文本 HTML 信息;
"script": 返回純文本 JavaScript 代碼。
"json": 返回 JSON 數據 |
-
案例:
1、前端需要做什么?
- 以何種形式展示:web網頁展示
發送參數
獲取響應
局部刷新-修改DOM
2、后端需要做什么?
- 獲取商品類型,根據商品類型查詢商品
get請求
# 視圖 def select_all_goods_by_goodstype(request): """查看更多,根據商品類型查詢所有商品""" # 接收參數 goodstype_id = request.GET.get("goodstype_id") # 查詢數據 goods_qs = Goods.objects.filter(goodstype_id=goodstype_id) # 轉成列表字典格式 goods_list = [{"id": goods.id, "name": goods.name,"price":goods.price,"picture":goods.picture.name,"unite":goods.unite} for goods in goods_qs] # JsonResponse return JsonResponse(goods_list,safe=False,json_dumps_params={"ensure_ascii":False}) # 前端頁面 <script> // 根據url中的goodstype_id var url = window.location.href; var goodstype_id = url.split("?")[1].split("=")[1]; //發送請求 $.ajax({ "url": "/api/more/", "method": "get", "data": {"goodstype_id": goodstype_id}, "success": function (data) { {#console.log(data)#} {#console.log(typeof data)#} var divs = "" //遍歷 for(var i=0;i<data.length;i++){ var goods = data[i] var id = goods["id"] var name = goods["name"] var picture = goods["picture"] var price = goods["price"] var unite = goods["unite"] divs = divs+'<div class="col-xs-12 col-sm-3"><a href="detail.html" class="thumbnail"><img src="/static/ft/images/'+picture+'" class="img-responsive"></a><p class="text-center">'+name+'</p><p class="text-center myps"><span>¥'+price+'</span><span>'+price+'/'+unite+'</span><span><img src="/static/ft/images/carts.png"/></span></p></div>' } //修改dom,這里比較費勁 $("#mybody").html(divs) }, "error": function () { alert("error") } }) $.ajax({ "url": "/api/goodstype/", "method": "get", "data": {"goodstype_id": goodstype_id}, "success": function (data) { $("#goodstype").html("全部分類 > "+data["name"]) }, "error": function () { alert("error") } }) </script>
- 以何種形式展示:web網頁展示
五、前端渲染
我們可以使用JS中的text、innerHtml、append 等方法,但是比較麻煩,我們可以使用Vue框架中的語法
-
Vue介紹
Vue 是一套用於構建用戶界面的JavaScript框架,前端使用Vue的目的就是把AJAX里面的數據綁定到前端
-
Vue基本語法
-
下載引入
-
1、第一個應用
在Django的模版中使用Vue時,語法沖突,需要增加標簽verbatim處理
Vue.js的應用可以分為2個重要的組成部分,一個是視圖(也就是HTML代碼)另外一個是腳本
-
# Vue使用[[]]語法 "delimiters":["[[","]]"]
-
2、v-bind 常用於綁定屬性
<a v-bind:href="url">百度</a>
-
v-if 指令用於條件性地渲染一塊內容。這塊內容只會在指令的表達式返回 true值的時候被渲染
<div id="app"> <div v-if="type === 'A'"> A </div> <div v-else-if="type === 'B'"> B </div> <div v-else-if="type === 'C'"> C </div> <div v-else> Not A/B/C </div> </div> <script> new Vue({ el: '#app', data: { type: 'C' } }) </script>
- v-for 可以通過一個對象的屬性來迭代數據
<div id="app"> <ul> <li v-for="value in object"> {{ value }} </li> </ul> </div> <script> new Vue({ el: '#app', data: { object: { name: '菜鳥教程', url: 'http://www.runoob.com', slogan: '學的不僅是技術,更是夢想!' } } }) </script>
- 可以用 v-on 指令監聽 DOM 事件,並在觸發時運行一些 JavaScript 代碼
<div id="app"> <button v-on:click="counter += 1">增加 1</button> <p>這個按鈕被點擊了 {{ counter }} 次。</p> </div> <script> new Vue({ el: '#app', data: { counter: 0 } }) </script>
-
Vue異步請求
<div id="box"> <input type="button" @click="get()" value="點我異步獲取數據(Get)"> </div> <script type = "text/javascript"> window.onload = function(){ var vm = new Vue({ el:'#box', data:{ msg:'Hello World!', }, methods:{ get:function(){ //發送get請求 this.$http.get('/try/ajax/ajax_info.txt').then(function(res){ document.write(res.body); },function(){ console.log('請求失敗處理'); }); } } }); } </script>
-
案例:商品中 查看更多 功能
1、導入包
2、使用Vue,搭建環境
<script> // 根據url中的goodstype_id var url = window.location.href; var goodstype_id = url.split("?")[1].split("=")[1]; //創建VUE對象 new Vue({ el: "#mybody", delimiters: ["[[", "]]"], data: { goods_list: [], }, methods: { select_info: function () { this.$http.get("/api/more/?goodstype_id="+goodstype_id).then(function (content) { //console.log(content) //console.log(content.data) this.goods_list = content.data },function (data) { alert("error") }) } }, mounted:function () {//相當於js onload表示窗體加載完畢 this.select_info() } }) </script>
3、使用Vue綁定
<div class="panel-body" id="mybody"> <div class="col-xs-12 col-sm-3" v-for="goods in goods_list"> <a href="detail.html" class="thumbnail"> <img v-bind:src="'/static/ft/images/'+[[goods.picture]]" class="img-responsive"> </a> <p class="text-center">[[goods.name]]</p> <p class="text-center myps"><span>¥[[goods.price]]</span><span>[[goods.price]]/[[goods.unite]]</span><span><img src="/static/ft/images/carts.png"/></span></p> </div> </div>
-
六、REST
REST(Representational State Transfer的簡稱,中文翻譯為“表現層狀態轉移”)與技術無關,
是一種軟件架構風格、設計風格,而不是標准,只是提供了一組設計原則和約束條件。基於這個風格
設計的軟件可以更簡潔,更有層次,更易於實現緩存等機制
滿足這些約束條件和原則的應用程序或設計就是 RESTful
REST需要遵循如下10條規則:
1、協議
API與用戶的通信協議,總是使用HTTPS協議
2、域名
在域名上進行區分,例如
子域名方式:
www.ujiuye.com 所有人都知道這是訪問網站
api.ujiuye.com(cts.ujiuye.com) 看到這個網站就就知道返回json、xml數據
Url上區分:
www.ujiuye.com/
www.ujiuye.com/api/ (添加一個api 目錄,讓人一看到就知道是一個接口)
3、版本
因為項目存在着版本迭代更新,因此建議在url上添加版本
www.ujiuye.com/api/v1/
http://www.example.com/app/1.0/foo
v1、1.0: 就是代表第一版
4、路徑
網絡上任何東西都是資源,均使用名詞表示(可復數)
通俗來說,URL不應該使用動作來描述。例如,下面是一些不符合統一接口 要求的URI:
GET:/getUser/1、 POST:/createUser、PUT:/updateUser/1 、DELETE:/deleteUser/1
建議使用 /user/1
5、HTTP動詞
對於資源的具體操作類型,由HTTP動詞表示
常用的HTTP動詞有下面四個(括號里是對應的SQL命令)
GET(SELECT):從服務器取出資源(一項或多項)
POST(CREATE):在服務器新建一個資源
PUT(UPDATE):在服務器更新資源(客戶端提供改變后的完整資源)
DELETE(DELETE):從服務器刪除資源
還有三個不常用的HTTP動詞
PATCH(UPDATE):在服務器更新(更新)資源(客戶端提供改變的屬性)
HEAD:獲取資源的元數據
OPTIONS:獲取信息,關於資源的哪些屬性是客戶端可以訪問改變的
下面是一些例子
GET /zoos:列出所有動物園
POST /zoos:新建一個動物園(上傳文件)
GET /zoos/ID:獲取某個指定動物園的信息
PUT /zoos/ID:更新某個指定動物園的信息(提供該動物園的全部信息)
PATCH /zoos/ID:更新某個指定動物園的信息(提供該動物園的部分信息)
DELETE /zoos/ID:刪除某個動物園
GET /zoos/ID/animals:列出某個指定動物園的所有動物
DELETE /zoos/ID/animals/ID:刪除某個指定動物園的指定動物
6、過濾信息
如果記錄數量很多,服務器不可能都將它們返回給用戶。API應該提供參數,過濾返回結果。
下面是一些常見的參數
?limit=10:指定返回記錄的數量
?offset=10:指定返回記錄的開始位置
?page=2&per_page=100:指定第幾頁,以及每頁的記錄數
?sortby=name&order=asc:指定返回結果按照哪個屬性排序,以及排序順序
?animal_type_id=1:指定篩選條件
參數的設計允許存在冗余,即允許API路徑和URL參數偶爾有重復 比如:
GET /zoos/ID/animals
GET /animals?zoo_id=ID
二者含義是相同的
7、狀態碼
服務器向用戶返回的狀態碼和提示信息,常見的有以下一些(方括號中是該狀態碼對應的HTTP動詞)。
200 OK - [GET]:服務器成功返回用戶請求的數據
201 CREATED - [POST/PUT/PATCH]:用戶新建或修改數據成功。
202 Accepted - []:表示一個請求已經進入后台排隊(異步任務)
204 NO CONTENT - [DELETE]:用戶刪除數據成功。
400 INVALID REQUEST - [POST/PUT/PATCH]:用戶發出的請求有錯誤,服務器沒有進行新建或修改數據的操作
401 Unauthorized - []:表示用戶沒有權限(令牌、用戶名、密碼錯誤)
403 Forbidden - [] 表示用戶得到授權(與401錯誤相對),但是訪問是被禁止的。
404 NOT FOUND - []:用戶發出的請求針對的是不存在的記錄,服務器沒有進行操作,該操作是冪等的
406 Not Acceptable - [GET]:用戶請求的格式不可得(比如用戶請求JSON格式,但是只有XML格式)
410 Gone -[GET]:用戶請求的資源被永久刪除,且不會再得到的
422 Unprocesable entity - [POST/PUT/PATCH] 當創建一個對象時,發生一個驗證錯誤
500 INTERNAL SERVER ERROR - [*]:服務器發生錯誤,用戶將無法判斷發出的請求是否成功
8、錯誤處理
如果狀態碼是4xx,服務器就應該向用戶返回出錯信息。一般來說,返回的信息中將error作為鍵名,出錯信息作為鍵值即可。
{error: "Invalid API key"}
9、返回結果
針對不同操作,服務器向用戶返回的結果應該符合以下規范。
GET /collection:返回資源對象的列表(數組)
GET /collection/resource:返回單個資源對象
POST /collection:返回新生成的資源對象
PUT /collection/resource:返回完整的資源對象
PATCH /collection/resource:返回完整的資源對象
DELETE /collection/resource:返回一個空文檔
10、超媒體
RESTful API最好做到Hypermedia(即返回結果中提供鏈接,連向其他API方法),使得用戶不查文檔,也知道下一步應該做什么
比如,Github的API就是這種設計,訪問api.github.com會得到一個所有可用API的網址列表
{
"current_user_url": "https://api.github.com/user",
"authorizations_url": "https://api.github.com/authorizations",
// ...
}
從上面可以看到,如果想獲取當前用戶的信息,應該去訪問api.github.com/user,然后就得到了下面結果
{
"message": "Requires authentication",
"documentation_url": "https://developer.github.com/v3"
}
上面代碼表示,服務器給出了提示信息,以及文檔的網址
11、其他
服務器返回的數據格式,應該盡量使用JSON,避免使用XML