
如何快速實現REST API集成以優化業務流程
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.37)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>
對于Linux和Mac OS用戶,您可以在CLI中鍵入此命令以顯示已安裝的python版本;
$ python -V
Python 3.6.3
由于本教程將使用Django 2.0,因此如果您的開發機器上尚未安裝,我建議您安裝Python 3.4、3.5或3.6的最新版本。
在安裝Python之后,您可以繼續執行以下步驟來為您的API項目創建一個工作目錄,并設置一個虛擬環境。
對于Linux和Mac OS用戶,您可以在命令行界面(CLI)中輸入以下命令來設置工作目錄和虛擬環境:
$ mkdir music_service && cd music_service
# creates virtual enviroment named venv
music_service$ virtualenv --python=python3 venv
# activate the virtual enviroment named venv
music_service$ source venv/bin/activate
在使用DRF構建API之前,您需要首先在之前創建的虛擬環境中安裝django
。
(venv)music_service$ pip install Django==2.0.3
安裝django
后,繼續在前面創建的虛擬環境中安裝djangorestframework
。
(venv)music_service$ pip install djangorestframework
在設置好你的開發環境之后,繼續創建一個django項目;
(venv)music_service$ django-admin.py startproject api .
(venv)music_service$ cd api
然后創建一個 Django 應用程序;
(venv)music_service$ django-admin.py startapp music
此時,目錄結構現在應如下所示;
api/
manage.py
api/
__init__.py
settings.py
urls.py
wsgi.py
music/
migrations/
__init__.py
__init__.py
admin.py
apps.py
models.py
tests.py
views.py
venv/
在創建項目和應用程序之后,接下來您需要首次同步數據庫,并創建一個初始用戶,同時為該用戶設置密碼。
(venv)music_service$ python manage.py migrate
(venv)music_service$ python manage.py createsuperuser --email admin@example.com --username admin
現在,請打開api/settings.py
文件,并將rest_framework
和music
應用程序添加到INSTALLED_APPS
配置中。
INSTALLED_APPS = [
...
'rest_framework',
'music'
]
此外,打開api/urls.py
文件并為music
應用程序添加URL;
...
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('music.urls'))
]
在本教程中,我采用了與Django一同提供的默認SQLite作為關系數據庫管理系統(RDBMS),當然,您也可以選擇使用PostgreSQL或其他您偏好的RDBMS。
至此,您的項目設置已經完成,接下來就可以開始為音樂服務API編寫代碼了。
沒有測試的代碼會按設計出錯。
— 雅各布·卡普蘭-莫斯
在著手編寫API的業務邏輯之前,編寫測試是至關重要的一步。我傾向于先為單個視圖編寫一個單元測試,然后逐步更新代碼以確保該測試能夠通過。
為了演示這種方法,我們將為返回所有歌曲的端點(即GET /songs/
)創建一個測試。
請打開music/tests.py
文件,并在其中添加相應的代碼。
from django.urls import reverse
from rest_framework.test import APITestCase, APIClient
from rest_framework.views import status
from .models import Songs
from .serializers import SongsSerializer
# tests for views
class BaseViewTest(APITestCase):
client = APIClient()
@staticmethod
def create_song(title="", artist=""):
if title != "" and artist != "":
Songs.objects.create(title=title, artist=artist)
def setUp(self):
# add test data
self.create_song("like glue", "sean paul")
self.create_song("simple song", "konshens")
self.create_song("love is wicked", "brick and lace")
self.create_song("jam rock", "damien marley")
class GetAllSongsTest(BaseViewTest):
def test_get_all_songs(self):
"""
This test ensures that all songs added in the setUp method
exist when we make a GET request to the songs/ endpoint
"""
# hit the API endpoint
response = self.client.get(
reverse("songs-all", kwargs={"version": "v1"})
)
# fetch the data from db
expected = Songs.objects.all()
serialized = SongsSerializer(expected, many=True)
self.assertEqual(response.data, serialized.data)
self.assertEqual(response.status_code, status.HTTP_200_OK)
此時,如果您嘗試運行測試,它將會失敗并報錯,原因是我們還沒有創建視圖文件和序列化器。
在編寫完測試之后,接下來我們需要編寫一個視圖來處理GET /songs/
請求。
模型:首先,我們需要創建一個模型,用于存儲歌曲的相關信息,這些信息將在響應中返回。請打開music/models.py
文件,并添加以下代碼行:
from django.db import models
class Songs(models.Model):
# song title
title = models.CharField(max_length=255, null=False)
# name of artist or group/band
artist = models.CharField(max_length=255, null=False)
def __str__(self):
return "{} - {}".format(self.title, self.artist)
由于我們使用的是Django,因此也可以將模型注冊到admin后臺。稍后,我們將展示如何利用admin后臺來添加歌曲,以便對手動測試這個端點進行輔助。接下來,請將以下代碼行添加到music/admin.py
文件中:
from django.contrib import admin
from .models import Songs
admin.site.register(Songs)
在那之后,
(venv)music_service$ python manage.py makemigrations
然后遷移;
(venv)music_service$ python manage.py migrate
序列化器:接下來,我們需要創建一個序列化器。序列化器的作用是將復雜的數據類型(例如查詢集和模型實例)轉換為Python的基本數據類型,這些數據類型隨后可以輕松地轉換為JSON、XML或其他內容類型。
請新建一個文件music/serializers.py
,并向其中添加以下代碼行:
from rest_framework import serializers
from .models import Songs
class SongsSerializer(serializers.ModelSerializer):
class Meta:
model = Songs
fields = ("title", "artist")
序列化器還具備反序列化的功能,這意味著在首先驗證傳入的數據之后,它可以將解析后的數據轉換回復雜的數據類型。Django REST framework中的序列化器的工作機制與Django的Form和ModelForm類頗為相似。
視圖:現在,我們來創建一個視圖,用于返回所有歌曲的信息。請打開music/views.py
文件,并向其中添加以下代碼行:
from rest_framework import generics
from .models import Songs
from .serializers import SongsSerializer
class ListSongsView(generics.ListAPIView):
"""
Provides a get method handler.
"""
queryset = Songs.objects.all()
serializer_class = SongsSerializer
對于使用Flask背景的開發者來說,在使用Django REST framework(DRF)構建API時,viewsets的概念可能類似于使用Resources。
在之前的代碼中,我們通過設置類的queryset
屬性來明確如何從數據庫中檢索對象,并通過指定serializer_class
來確定用于序列化和反序列化數據的序列化器。
然而,需要注意的是,此處的描述中存在一個小錯誤:代碼中的視圖并非繼承自generics.viewsetListViewSet
(因為這樣的類并不存在)。實際上,它可能是繼承自DRF提供的某個泛型視圖集類,例如viewsets.ModelViewSet
,該類結合了多個通用視圖的行為,并提供了標準的CRUD操作。
在運行測試之前,您必須通過配置 url 來鏈接視圖。
打開music/tests.py
文件并添加以下代碼行;
from django.contrib import admin
from django.urls import path, re_path, include
urlpatterns = [
path('admin/', admin.site.urls),
re_path('api/(?P<version>(v1|v2))/', include('music.urls'))
]
打開music/tests.py
文件并添加以下代碼行;
from django.urls import path
from .views import ListSongsView
urlpatterns = [
path('songs/', ListSongsView.as_view(), name="songs-all")
]
關鍵時刻已經到來。首先,讓我們來運行自動化測試。請執行以下命令:
(venv)music_service$ python manage.py test
shell中的輸出應該與此類似;
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
.
--------------------------------------------------------------------Ran 1 test in 0.010s
OK
Destroying test database for alias 'default'...
您同樣可以手動對這個端點進行測試。請在瀏覽器中訪問http://127.0.0.1:8000/admin
,然后使用您在項目設置階段所創建的超級用戶賬號和密碼進行登錄。成功登錄后,您將會看到一個管理界面。
點擊admin界面中的“MUSIC”下的“Songs”,您將會看到一個界面,它可能如下所示:
點擊“ADD SONGS
”按鈕,然后添加幾首歌曲用于測試。完成后,請在瀏覽器中導航到http://127.0.0.1:8000/api/v1/songs
。您將會看到一個界面,它列出了您剛剛添加的所有歌曲,并且以JSON格式呈現。
如果你能看到自己添加的歌曲,那就給自己來個掌聲吧!恭喜你,你的API已經成功運行了!
API是后端與前端客戶端之間的約定。API版本控制的功能在于,它允許你對不同客戶端的行為進行更改,并且能夠“優雅地”淘汰舊客戶端所使用的舊代碼。因此,為你的API添加版本控制是一個值得考慮的舉措。
要添加版本控制,請打開api/settings.py
文件并添加以下代碼行。
# ....
REST_FRAMEWORK = {
# When you enable API versioning, the request.version attribute will contain a string
# that corresponds to the version requested in the incoming client request.
'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning',
}
當啟用API版本控制時,request.version
屬性將包含與傳入客戶端請求中請求的版本對應的字符串。與下面的示例代碼一樣,我們可以訪問version
屬性并根據版本號更改API的行為。
# ...
def list(self, request, *args, **kwargs):
if self.request.version == 'v1':
pass
# you can put here business logic that
# is specific to version 1
pass
# You can put here the current version
# business logic
# ...
到目前為止,我們已經見識到使用Django REST framework(DRF)創建API是多么輕松易行。在本教程中,為了保持內容的簡潔明了,我只實現了一個API端點,目的是讓您初步了解如何使用這個框架但實際上,利用DRF,您可以構建一個功能強大的API。
下表列出了本項目中實現的所有端點的完整清單。如果您想查看API示例的完整實現,請訪問我的GitHub倉庫,您可以對其進行分叉(fork),并在學習過程中自由地進行嘗試和修改。
1 | Endpoint | HTTP Method | CRUD Method | Response |
2 | songs/ | GET | READ | Get all songs |
3 | songs/:id/ | GET | READ | Get a single song detail |
4 | songs/ | POST | CREATE | Add a song |
5 | songs/:id/ | PUT | UPDATE | Update a single song |
6 | songs/:id/ | DELETE | DELETE | Delete a single song |
POST
、PUT
和DELETE
向資源提交數據的表單。如果您正在著手構建API,我強烈推薦您查閱以下資源。這些資源是構建API時不可或缺的最佳實踐指南。
此外,官方的DRF和Django文檔也是您不可或缺的參考資料。
同時,我還發現cdrf.co這個資源非常有用。它詳細闡述了DRF框架中所有類的結構和功能,幫助您更深入地了解DRF的底層實現。
在接下來的第二部分中,我將深入探討DRF中的身份驗證和權限機制,并展示如何將這些機制應用于音樂服務API端點。
希望這篇文章對您有所幫助。
原文鏈接:https://medium.com/backticks-tildes/lets-build-an-api-with-django-rest-framework-32fcf40231e5