本文作者:Eric
作者 Github : https://github.com/Ratherman
自由團隊將從0到1 手把手教各位讀者學會(1)Python基礎語法、(2)Python Web 網頁開發框架 – Django 、(3)Python網頁爬蟲 – 周易解夢網、(4)Tensorflow AI語言模型基礎與訓練 – LSTM、(5)實際部屬AI解夢模型到Web框架上。
AI . FREE Team 讀者專屬福利 → Python Basics 免費學習資源
用 rest framework 建立 API
在今天會進入更後端一點的世界,我們會實作出幾支 API去處理來自用戶端的特定 Request。在這邊會提到的 Requests 總共有3個, GET, POST, 和 DELETE。
Request,表示用戶透過特定的方式"請求"伺服器端做一些操作,在這兩天的會用到的例子,都會與資料庫的操作有關係。另外,如果有牽涉到回傳或是上傳的部分,我們通常都會將資料格式轉換成 JSON 的形式(與 Python 的 List 很像,基本的格式為 {"key": “value”})。像是下方的圖片,為等一下會做出來專門處理GET Request 的API所回傳的資料,為標準的 JSON 格式。
單純用來取得資料。
例子: 取得所有學派的資料。
發出 Request 時,會伴隨其他參數。
例子: 新增所有學派的資料,除了發 request 以外還需要伴隨新的學派的資訊。
發出 Request 刪除資料庫的特定內容,會伴隨其他參數。
例子: 刪出某個古人的資料,也需要伴隨能夠古人的資訊(如 id, name)。
我們今天會使用到 Django RestFramework 這個套件,來簡潔的實現API的建立。
在我們進入到下一步驟之前,先來探討 API 這個概念,英文全名是 Application Programming Interface,而中文翻譯是應用程式介面,使用者端不需要知道應用程式是如何運作的,使用者只需要知道該怎麼使用 API 就好了。生活中其實隨處可見 API 的例子,以買飲料為例,我們去飲料機投硬幣得到飲料。在這個動作裡面,飲料機就是這個動作的介面 (Interface),它負責接收硬幣,然後回傳飲料給使用者。類比到我們的使用情境,我們想要API 做到的事情是,接收到 Requests (GET, POST, DELETE)之後,會回傳給使用者一個他們需要的內容。
有了 Request 和 API 的基本概念後,我們就來安裝上面提到的 rest framework 套件吧。先進入虛擬環境,然後再安裝。
$ pipenv shell $ pipenv install djangorestframework
成功安裝之後,打開 DI_project 中的設定檔,也就是 DI_project/ settings.py,在前幾天也有提過的 INSTALLED_APPS 這個 list 結構再多加入 "rest_framework" 這個APP,所以最後會變成下面這樣。
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'demo_app.apps.DemoAppConfig', 'rest_framework', ]
新增檔案 (demo_app/ serializers.py)
首先需要在 demo_app 內多增加一個檔案,並將它命名為 serializers.py,因為它的工作就是將一連串的 model objects (ex: 學派),序列化地轉換成 JSON 格式的資料。而檔案命名使用複數(s)呈現的理由和 urls.py、views.py 是類似的,就是因為我們會有 class 是針對 Ancient_People 做 serialize、也會有 class 是針對 School 做 serialize,所以才取名為複數型。
完成上面的設定之後,我們就可以進入撰寫 API 的部分了。
首先,為了讓 Requesets 可以順利地進行,我們先將做出 serialize 的工具做好,所以先將以下內容放進 serializers.py 內。
DI_project/ demo_app/ serializers.py
from rest_framework import serializers from demo_app.models import School class School_Serializer(serializers.ModelSerializer): class Meta: model = School fields = "__all__"
我們在這裡需要先 import rest_framework
的 serializers,然後再 import 同為 demo_app 資料夾底下的 models.py 裡面的兩個class (i.e. Ancient_People 和 School)。接著,我們看到了兩層 class 的結構,在裡面那層 Meta 的 class 必須要設定2個變數。
model:
我們將 School (學派) assign 給此變數,就是因為我們希望這個 School_Serializer 能夠針對 School 這個 model 做序列化。
fields:
我們將此變數設定為 "all",表示我們希望對 School 內所有的欄位都做序列化。待會我們看到成果的時候就會實際的看到完整資料的回傳。
在有上面 serializers.py 的幫助下,等等的操作就會變得相當容易。在今天我們會先完成 查(GET)這部分的API,而在明天則會依照新增(POST)、修改(還是POST)、刪除(DELETE)的順序完成。
這裡我們寫3種查
列出所有預計完成的API
列出所有的學派資料
列出特定學派的資料
開啟 demo_app/ views.py,將以下內容加入。
from rest_framework.decorators import api_view from rest_framework.response import Response from demo_app.serializers import School_Serializer @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(['GET']) def school_list(request): schools = School.objects.all() serializer = School_Serializer(schools, many=True) return Response(serializer.data) @api_view(['GET']) def school_detail(request, id): one_school = School.objects.get(id=id) serializer = School_Serializer(one_school, many=False) return Response(serializer.data)
首先我們先看 import 的部分,這次我們從 rest_framework 的方法中 import 了 api_view
和 Response
。api_view
在這邊可以設定我們的 API 支援什麼樣的 Request,以目前上方有的 API 為例,全部都是只有支援 GET 類型的 Request。另外,我們也有 import demo_app.serializers
,因為我們馬上就會在這個 views.py 馬上就使用到了(i.e. School_Serializer)。
api_overview 這支API內我們一共列了5個待開發的API,大家可以注意到,我們在這邊有刻意的把資料的結構換成 JSON 的形式,也就是 { "key1": “value1”, “key2”: “value2”, ...},必須要這樣才能透過來自 rest_framework 的 Response 方法將資料傳給請求方。
接著我們看最下面那支 API (i.e. school_detail
),這支有懂,那上面那支就一定沒有問題了! 我們在這裡可以看到 school_detail
除了接收 HttpRequest 以外,還有接收 id 這個變數,這是從 url pass 進來的,我們需要這個 id 將特定的 Shcool object 取出來。(這裡算是重複了 urls.py, views.py 交互的概念)
接下來我們實體化了 School_Serializer
這個 class,想要實體化就需要提供兩個參數,一個是學派的 Object (i.e. 上面的 one_school),另一個則是 many 的設定,如果是 False
,那就表示我們只會 serialize 一個學派Object;如果是 True
的話,則表示我們預計會 serialize 不只一個學派Object,這邊的使用情境可以參考 school_list 這支API。
處理完 view 之後,我們再來把 url 也設計好。
開啟 demo_app/ urls.py,並將 urlpatterns 調整的與下方一致。在這邊,我們一起將其他尚未完成,但預計會完成的 path 也一併加入。(就是註解起來的部分)
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") ]
至此,我們就算是階段性的完成了 GET Request 的API了,將 server run 起來。
$ python manage.py runserver
開啟瀏覽器,並搜尋以下 url,在這邊同時也呈現我看到的畫面。
對應到 name = api_overview 的 url: http://127.0.0.1:8000/demo_app/
對應到 name = school_list 的 url: http://127.0.0.1:8000/demo_app/school_list
對應到 name = school_detail/int:id 的 url: http://127.0.0.1:8000/demo_app/school_detail/7
Note: 這邊大家的 id 數字可能會不一樣喔,可以看看大家在上面的 name = school_list 有列出來的學派 id 為何,像我就是在 school_list 看到7,所以這邊的 school_detail 才用7。
有成功執行的各位,可以看在對應的URL裡看到有被自動生成的介面(此為今天下載的套件 Rest framework 產生的)。伴隨著回傳JSON型式的結果,也可以看到其他相關的資訊。
以(上圖) School Detail 為例的話:
請求內容: GET /demo_app/school_detail/7
回傳資訊
狀態: HTTP 200 OK (表示成功 request,也有成功得到 回傳值。)
其他相關的回傳值...
JSON Data
今天提到了 API 和 Request 的基本概念,透過 Serializer 的協助,我們很快速的將針對 GET Request 的 API 建立起來了。在明天,我們會用兩種請求(一個是 POST,另一個則是 DELETE) 實作出能夠讓使用者 新增、修改、和刪除 的API。
自由團隊 官方網站: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/
文章同步發布於:第十二屆 IT 挑戰賽部落格