iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 23
1
Modern Web

🍐放學後的網頁開發系列 第 23

[Day23] 柚子放學後的網頁生活 - Django 前後端分離

今天來點綴我們的網站,把程式碼分割的更清楚吧 !

RESTful API

在講RESTful API前,先說說REST
全名為Representational State Transfer,通常說它是一種網路架構風格,而不是一種標準

Q:為什麼加 ful ?
想像成名詞->形容詞,beauty->beautiful
那我們就說系統如果是REST式的,就稱做RESTful

RESTful 用來對資料的操作 ( CRUD )提供API的接口,這些操作正好對應HTTP提供的GET、POST、PUT、DELETE

REST:https://zh.wikipedia.org/wiki/%E8%A1%A8%E7%8E%B0%E5%B1%82%E7%8A%B6%E6%80%81%E8%BD%AC%E6%8D%A2
API:https://zh.wikipedia.org/zh-tw/%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E6%8E%A5%E5%8F%A3

Q:為什麼說 " 風格 "?

一般來說,假設我們要設計會員系統的 API,可能會有以下方式來作為 API 的 interface:

  • 獲取使用者資料 /getAllUsers
  • 獲取使用者資料 /getUser/1
    • 後面數字常為第幾筆、ID ( 自定義 )
  • 新增使用者資料 /createUser
  • 更新使用者資料 /updateUser/1
    • 後面數字常為第幾筆、ID ( 自定義 )
  • 刪除使用者資料 /deleteUser/1
    • 後面數字常為第幾筆、ID ( 自定義 )

那如果說改成REST風格,對應上面 GET、POST、PUT、DELETE 也能清楚知道功用

  • 獲取使用者資料 /GET /users
  • 獲取使用者資料 /GET /user/1
  • 新增使用者資料 /POST /user
  • 更新使用者資料 /PUT /user/1
  • 刪除使用者資料 /DELETE /user/1

Q:那兩者有差嗎?
有差! 明顯的直觀很多,也方便許多

Define our RESTful

開始之前,先定義好我們要用的GET、POST、PUT、DELETE

  • 取得所有照片列表 /GET /photos
  • 取得 id = 1 的照片資料 /GET /photos/1
  • 新增照片 /POST /photos
  • 更新 id = 1 的照片資料 /PUT /photos/1
  • 刪除 id = 1的照片資料 /DELETE /photos/1

Startapp - photos

在開始前,我們先建立一個app專門負責photos的操作

還記得嗎

python manage.py startapp photos

接著確認成功後就可以到 urls 加上

from photos.views import get_photos_api

#urlpatterns內
url(r'^api/photos$',get_photos_api')

再來設計我們的View

from django.http import JsonResponse
from django.core import serializers

def get_photos_api(request):
    photos = Photo.objects.all()
    data = serializers.serialize('json',photos)
    return JsonResponse({'data':data})

這邊測試把所有DB裡面的資料讀出來,再轉成json檔做Serialize把資料串一起return
Serializers:https://www.django-rest-framework.org/api-guide/serializers/

回網頁看 api/photos 的頁面

成功後我們先放著去改index
原本我們的index get整個列表是由Django提供的方法render出來

{% for photo in Photos %}
<div class="col-xs-6 col-md-3" style="margin-left:50px;">
    <h2>{{photo.title}}</h2>
    <a href="#" class="thumbnail"><img src="{{photo.path}}" alt="" width="300" ></a>
    <p>{{photo.story}}</p>
    <p>{{photo.create_date}}</p>
</div>
{% endfor %}

前端交給JS,後端負責API
我們用XMLHttpRequest來完成API
XMLHttpRequest:

  1. https://developer.mozilla.org/zh-TW/docs/Web/API/XMLHttpRequest
  2. https://zh.wikipedia.org/wiki/XMLHttpRequest

先把剛剛上面的form槓掉

<div class="row">
    <div id="render">
    <!--
    {% for photo in Photos %}
    <div class="col-xs-6 col-md-3" style="margin-left:50px;">
         <h2>{{photo.title}}</h2>
         <a href="#" class="thumbnail"><img src="{{photo.path}}" alt="" width="300" ></a>
         <p>{{photo.story}}</p>
         <p>{{photo.create_date}}</p>
    </div>
    {% endfor %}
    -->
    </div>
</div>

裡面多了個div ( id = render )等等要讓 js 把資料 render 進去

<script>
var xhr = new XMLHttpRequest();
var onloadHandle = function(){
  var data = JSON.parse(JSON.parse(xhr.responseText).data);
  var result = document.getElementById('render');
  var str='';
  data.forEach(function(value){
    str += '<div class="col-xs-6 col-md-3" style="margin-left:50px;"><h2>'+value.fields.title+'</h2><a href="#" class="thumbnail"><img src="'+value.fields.path+'" alt="" width="300" ></a><p>'+value.fields.story+'</p><p>{{photo.create_date}}</p></div>'
  });
  result.innerHTML = str; 
};
xhr.open('GET','http://localhost:8000/api/photos',true);
xhr.send(); xhr.onload = onloadHandle;
</script>

再回到頁面看就能看到一樣的內容囉~

下課囉 ~ 請鎖定 柚子放學後的網頁生活


上一篇
[Day22] 柚子放學後的網頁生活 - Log in / out
下一篇
[Day24] 柚子放學後的網頁生活 - Web Crawler
系列文
🍐放學後的網頁開發30

尚未有邦友留言

立即登入留言