iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 10
0
自我挑戰組

零基礎成為 AI 解夢大師秘笈系列 第 10

【零基礎成為 AI 解夢大師秘笈】Day10 - Django VII

  • 分享至 

  • xImage
  •  

斜槓學習 – 零基礎成為 AI 解夢大師秘笈

前言

系列文章簡介

大家好,我們是 AI . FREE Team - 人工智慧自由團隊,這一次的鐵人賽,自由團隊將從0到1 手把手教各位讀者學會 (1)Python基礎語法 (2)Python Web 網頁開發框架 – Django (3)Python網頁爬蟲 – 周易解夢網 (4)Tensorflow AI語言模型基礎與訓練 – LSTM (5)實際部屬AI解夢模型到Web框架上。

為什麼技術要從零開始寫起

自由團隊的成立宗旨為開發AI/新科技的學習資源,提供各領域的學習者能夠跨域學習資料科學,並透過自主學習發展協槓職涯,結合智能應用到各式領域,無論是文、法、商、管、醫領域的朋友,都可以自由的學習AI技術。

資源

AI . FREE Team 讀者專屬福利 → Python Basics 免費學習資源

今日目標

  • 用 rest framework 建立 API

教學開始

相信經過昨天的內容,大家對於 Django APP 內部程式的交互又更熟練了,相信(也希望)大家有那種自己真的在開發一個軟體的感覺。我們目前使用了 rest framework 這個套件,就是想開發一個服務(API接口服務),能依據使用者不同的 Request 有不一樣的回傳值(JSON)。在今天,我們會延伸昨日的內容,往(POST)新增、修改,和(DELETE)刪除邁進!

1 複習觀念

首先,我們來看看昨天在 demo_app/ views.py 的片段內容。

from rest_framework.decorators import api_view
from rest_framework.response import Response
 
@api_view(['GET'])
def api_overview(request):
    api_urls = {
        'Schools List':'/school_list',
        'School Detail View':'/school_detail/<int:id>',
        'School Create':'/school_create',
        'School Update':'/school_update/<int:id>',
        'School Delete':'/task-delete/<int:id>'
    }
    return Response(api_urls)

以下段落算是複習,也算是加強概念。上方的 @api_view,是來自安裝套件「rest_framework」的方法,我們利用了這個decorators描述了下面的 api 準備要來接收什麼樣的 Request (i.e GET)。所以針對上面的內容, api_overview,就是一個拿來 GET 的 API。

當 server run 起來之後,有人去GET 右邊的這個連結 (http://127.0.0.1:8000/demo_app/),將會看到下方的圖片(在 urls.py 的 urlpattern 有設定好的前提下)。

https://ithelp.ithome.com.tw/upload/images/20200925/20130712mXKpszhXEy.png

這是用來呈現我們的這個 APP 有提供什麼樣的 API 服務,有點大綱的感覺,大家可以再注意到兩件事情:

  • 上圖的顯示結果以及 view 程式碼最後的回傳值都是 JSON 格式。在這裡的 api_overview,回傳內容是我們自己手刻的,但是在與 model 之間會發生交互的操作裡頭,我們就會需要使用到 serializer。
  • 這個 overview 的用意是希望使用者(client端),能夠一眼就知道我們的網址有什麼目的而且可以怎麼用,像是第二個 Key-Value Pair"School List":"/school_list",它的存在意義就是用來列出「學派」,然後使用者(client端)想要使用的話,那就要"請求"右方的網址。http://127.0.0.1:8000/demo_app/school_list

我們於上圖分別看到了,名字為 "school_create","school_update", 及 "school_delete" 的 path Object,在設計上,在這邊所對應到的 view 也告訴了我們,如果這個 path object 它被 Request 到的話,它會接著去找哪一支 view。所以我們可以想像,等等在開發 views.py 的時候,應該會要有如下圖的結構。

@api_view(['????'])
def school_create(request):
    # 處理邏輯和 query 的部分
    return Response(JSON Form Data)
 
@api_view(['????'])
def school_update(request, id):
    # 處理邏輯和 query 的部分
    return Response(JSON Form Data)
 
@api_view(['????'])
def school_delete(request, id):
    # 處理邏輯和 query 的部分
    return Response(...)

在方法 school_update 及 school_delete,之所以會在 input variable 使用到 id,是因為在 path object 的 url 就有傳到這個值了。而這件事情也合理,因為我們如果想要更新東西(school_update) 或是 刪東西(school_delete),正常來說會先需要定位我們想要操作的對象,而在這邊我們就是使用到id來定位(其實就是等等會看到對資料庫 query 的部分)。

那麼上面三個 @api_view 應該會分別對應到哪個 Request 方法呢?

它們的答案由上至下依序是 "POST", "POST", "DELETE",POST 除了在昨天提到提到可以專門用來應付寫入資料(Insert Data)的需求外,其實還可以再多做一件事情,那就是更新資料(Update Data),所以才會在這裡都用到 POST。

2 POST(增)

裡先從 view 開始寫起,先把針對「新建學派的API」寫好吧!
打開 demo_app/ views.py,並將以下內容寫入。

@api_view(['POST'])
def school_create(request):
    serializer = School_Serializer(data=request.data)
    if serializer.is_valid():
        serializer.save()
    return Response(serializer.data)

因為 views.py 裡面的方法會越來越多,所以這邊就不全部列出,僅會列出部分的程式碼,大家就
選一個適合的地方放入這段程式碼即可。

通常我們想要對資料庫做類似 insert/create/update 的動作,會對應到的 Request 就會是 POST,原因在昨天稍有提及,client 端在做這個操作的時候,同時會提供一組資料(JSON形式),所以就不會是單純的 GET,而會是 POST。至於client端要如何「提供另外一組資料」,待會我們就會在成果看到了!

在這個 function 的內部都是之前沒有在 Django Shell Command 看過的內容,在這邊我們是使用到來自 rest framework 的 serializer 裡面的工具,將收到的 POST Request 中伴隨的資料轉換成資料庫可以接受的形式,也就是 Object,在這裡的例子就是把 request.data 轉換成 School Object(i.e. serializer)。

最後的條件判斷(i.e. serializer.is_valid())則是在看 Request 的資料合不合法,"is_valid()" 會檢查我們傳給 API 的東西是不否有符合我們最初在 model.py 裡面的設計,如果是符合的,那它就會回傳 True,這樣就會進到條件裡面並將資料寫入資料庫裡面。

接著我們回頭看看昨天已經寫好的 demo_app/ urls.py ,其中下面三行的部分原本是有註解掉的,但現在要用到 school create 了,所以要記得把倒數第三個path object前面的註解拿掉,變得和下面一樣喔。

urlpatterns = [
    path("Confucianism/<int:id>", views.confucianism_detail, name="confucianism"),
    path("Taoism/<int:id>", views.taoism_detail, name="taosim"),
    path("", views.api_overview, name="api_overview"),
    path("school_list", views.school_list, name="school_list"),
    path("school_detail/<int:id>", views.school_detail, name="school_detail"),
    # 以下為今日開發時,會使用到的內容
    path("school_create", views.school_create, name="school_create"),
    #path("school_update/<int:id>", views.school_update, name="school_update"),
    #path("school_delete/<int:id>", views.school_delete, name="school_delete")
]

確定對應到它(views.school_create)的 url("school_create")也設定好了,所以我們已經準備齊全,可以面對 POST Request 的 API 了!

3 POST 階段成果

將此 Django 專案 run 起來。

$ python manage.py runserver

然後開啟瀏覽器,前往 http://127.0.0.1:8000/demo_app/school_create ,大家應該都要可以看到以下畫面。
https://ithelp.ithome.com.tw/upload/images/20200925/20130712Pbf0y1zt55.png

與昨天在 school list (i.e.http://127.0.0.1:8000/demo_app/school_list) 呈現的不太一樣,在這邊多新增了一個可以輸入文字的區塊。不過當然我們在這邊,會只輸入 School (學派)規定需要提供的內容而已(想知道需要什麼內容的話,可以參考我們自己在 demo_app/ models.py 的設計喔!)。

大家可以直接把下面的內容貼到文字區塊內

{
    "school_name":"AI_Free_Team",
    "core_value":"Learn and become stronger",
    "num_member": 999
}

並點選「POST按鈕」。

完成後,除了上方會顯示 HTTP 200 OK 等文字提示,我們也可以到昨天我們自己開發的 school_list 所對應的 url (i.e. http://127.0.0.1:8000/demo_app/school_list )看到已經多了一個學派了喔。
https://ithelp.ithome.com.tw/upload/images/20200925/20130712cKNr1XTDbg.png

4 POST(改) & DELETE(刪)

好,先把 demo_app/ urls.py 的最後兩個 path object 前面的註解也拿掉吧。

urlpatterns = [
    path("Confucianism/<int:id>", views.confucianism_detail, name="confucianism"),
    path("Taoism/<int:id>", views.taoism_detail, name="taosim"),
    path("", views.api_overview, name="api_overview"),
    path("school_list", views.school_list, name="school_list"),
    path("school_detail/<int:id>", views.school_detail, name="school_detail"),
    # 以下為今日開發時,會使用到的內容
    path("school_create", views.school_create, name="school_create"),
    path("school_update/<int:id>", views.school_update, name="school_update"),
    path("school_delete/<int:id>", views.school_delete, name="school_delete")
]

接著,我們打開 demo_app/ views.py 一次把剩下的修改,和刪除寫完吧!

改的部分:

@api_view(['POST'])
def school_update(request, id):
    school = School.objects.get(id=id)
    serializer = School_Serializer(instance=school, data=request.data)
    if serializer.is_valid():
        serializer.save()
    return Response(serializer.data)

刪的部分:

@api_view(['DELETE'])
def school_delete(request, id):
    school = School.objects.get(id=id)
    school.delete()
    return Response("Successfully Delete It.")

在這邊可以看到,想要做到這兩件事情的時候,都需要先利用我們在 Django Command Shell 有看過的方式,透過id"定位"出預期被操作的對象,取得之後才接著做下一階段的任務。以 school_update 而言,接下來會使用 serializer 幫助修改資料;而 school_delete,就相對單純了,只需要使用 school object 的 delete() 方法,就可以了。

5 POST and DELETE 成果

編輯完並且存檔之後,我們來看看修改資料會不會如期運作吧。
首先,我們用 GET 的方法看一下我們的學派分別對應到哪個 id,以下圖為例,是7。
URL: http://127.0.0.1:8000/demo_app/school_list
https://ithelp.ithome.com.tw/upload/images/20200925/20130712Lt1QIEhmvL.png

接著,就可以到修改對應到的URL了(注意: 最後面有 pass id=7 給school_update)
http://127.0.0.1:8000/demo_app/school_update/7
https://ithelp.ithome.com.tw/upload/images/20200925/201307127OySJMi7HN.png

其介面和 School Create 相當一致,我們在這邊就可以把新的資料寫進去,把學派名字稍微加長了一點,多了 Ver2 字眼。

{
        "school_name": "Confucianism Ver2",
        "core_value": "Benevolence and courtesy between people.",
        "num_member": 3952
}

接著點擊 POST 按鈕,都沒有問題的話,大家可以看到 HTTP 200 的提示,也可以回到 School_list 頁面看看是不是真的有改名喔。

最後我們來驗證 DELETE 的方法。
因為確定 id = 7 為有一個對應學派(是儒家),我們就直接到以下網址,把此學派刪掉。
https://ithelp.ithome.com.tw/upload/images/20200925/20130712KYvydGlPQZ.png
點擊右上角 DELETE 按鈕就完成了,相當容易! 回到 School_list 頁面,是不是看不見剛剛已經刪除的學派了呢?

6 邁向 AI 解夢大師 - 第九天

我們這兩天利用了 Django Rest Framework 實作出增刪改查API的服務,這件事情對前端的頁面
顯示其實相當重要,以臉書為例,在登入時我們輸入帳號密碼並且點選登入按鈕的動作,其實就觸發了 POST 的 Request,這個 Request 會被 臉書的 API 所接收,如果有驗證成功,才會回傳用戶的資訊(大頭貼、貼文、朋友等等),最後才再前端的部分,渲染(render)出色彩豐富的頁面。

當資料庫結構更為複雜時,API端口的設計就需要更多巧思。我們在這兩天一窺後端API的世界,希望大家有所收穫! 我們從明天開始會向前端發展,利用 bootstrap 框架撰寫網頁。大家可以先點擊操考連結中的網址認識一下 bootstrap,明天見!

7 參考連結

想更深入認識 AI . FREE Team ?

自由團隊 官方網站:https://aifreeblog.herokuapp.com/
自由團隊 Github:https://github.com/AI-FREE-Team/
自由團隊 粉絲專頁:https://www.facebook.com/AI.Free.Team/
自由團隊 IG:https://www.instagram.com/aifreeteam/
自由團隊 Youtube:https://www.youtube.com/channel/UCjw6Kuw3kwM_il39NTBJVTg/

文章同步發布於:自由團隊部落格
(想看更多文章?學習更多AI知識?敬請鎖定自由團隊的頻道!)


上一篇
【零基礎成為 AI 解夢大師秘笈】Day09 - Django VI
下一篇
【零基礎成為 AI 解夢大師秘笈】Day11 - Django VIII
系列文
零基礎成為 AI 解夢大師秘笈30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言