
如何快速實現(xiàn)REST API集成以優(yōu)化業(yè)務(wù)流程
[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,因此如果您的開發(fā)機器上尚未安裝,我建議您安裝Python 3.4、3.5或3.6的最新版本。
在安裝Python之后,您可以繼續(xù)執(zhí)行以下步驟來為您的API項目創(chuàng)建一個工作目錄,并設(shè)置一個虛擬環(huán)境。
對于Linux和Mac OS用戶,您可以在命令行界面(CLI)中輸入以下命令來設(shè)置工作目錄和虛擬環(huán)境:
$ 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構(gòu)建API之前,您需要首先在之前創(chuàng)建的虛擬環(huán)境中安裝django
。
(venv)music_service$ pip install Django==2.0.3
安裝django
后,繼續(xù)在前面創(chuàng)建的虛擬環(huán)境中安裝djangorestframework
。
(venv)music_service$ pip install djangorestframework
在設(shè)置好你的開發(fā)環(huán)境之后,繼續(xù)創(chuàng)建一個django項目;
(venv)music_service$ django-admin.py startproject api .
(venv)music_service$ cd api
然后創(chuàng)建一個 Django 應(yīng)用程序;
(venv)music_service$ django-admin.py startapp music
此時,目錄結(jié)構(gòu)現(xiàn)在應(yīng)如下所示;
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/
在創(chuàng)建項目和應(yīng)用程序之后,接下來您需要首次同步數(shù)據(jù)庫,并創(chuàng)建一個初始用戶,同時為該用戶設(shè)置密碼。
(venv)music_service$ python manage.py migrate
(venv)music_service$ python manage.py createsuperuser --email admin@example.com --username admin
現(xiàn)在,請打開api/settings.py
文件,并將rest_framework
和music
應(yīng)用程序添加到INSTALLED_APPS
配置中。
INSTALLED_APPS = [
...
'rest_framework',
'music'
]
此外,打開api/urls.py
文件并為music
應(yīng)用程序添加URL;
...
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('music.urls'))
]
在本教程中,我采用了與Django一同提供的默認(rèn)SQLite作為關(guān)系數(shù)據(jù)庫管理系統(tǒng)(RDBMS),當(dāng)然,您也可以選擇使用PostgreSQL或其他您偏好的RDBMS。
至此,您的項目設(shè)置已經(jīng)完成,接下來就可以開始為音樂服務(wù)API編寫代碼了。
沒有測試的代碼會按設(shè)計出錯。
— 雅各布·卡普蘭-莫斯
在著手編寫API的業(yè)務(wù)邏輯之前,編寫測試是至關(guān)重要的一步。我傾向于先為單個視圖編寫一個單元測試,然后逐步更新代碼以確保該測試能夠通過。
為了演示這種方法,我們將為返回所有歌曲的端點(即GET /songs/
)創(chuàng)建一個測試。
請打開music/tests.py
文件,并在其中添加相應(yīng)的代碼。
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)
此時,如果您嘗試運行測試,它將會失敗并報錯,原因是我們還沒有創(chuàng)建視圖文件和序列化器。
在編寫完測試之后,接下來我們需要編寫一個視圖來處理GET /songs/
請求。
模型:首先,我們需要創(chuàng)建一個模型,用于存儲歌曲的相關(guān)信息,這些信息將在響應(yīng)中返回。請打開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
序列化器:接下來,我們需要創(chuàng)建一個序列化器。序列化器的作用是將復(fù)雜的數(shù)據(jù)類型(例如查詢集和模型實例)轉(zhuǎn)換為Python的基本數(shù)據(jù)類型,這些數(shù)據(jù)類型隨后可以輕松地轉(zhuǎn)換為JSON、XML或其他內(nèi)容類型。
請新建一個文件music/serializers.py
,并向其中添加以下代碼行:
from rest_framework import serializers
from .models import Songs
class SongsSerializer(serializers.ModelSerializer):
class Meta:
model = Songs
fields = ("title", "artist")
序列化器還具備反序列化的功能,這意味著在首先驗證傳入的數(shù)據(jù)之后,它可以將解析后的數(shù)據(jù)轉(zhuǎn)換回復(fù)雜的數(shù)據(jù)類型。Django REST framework中的序列化器的工作機制與Django的Form和ModelForm類頗為相似。
視圖:現(xiàn)在,我們來創(chuàng)建一個視圖,用于返回所有歌曲的信息。請打開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背景的開發(fā)者來說,在使用Django REST framework(DRF)構(gòu)建API時,viewsets的概念可能類似于使用Resources。
在之前的代碼中,我們通過設(shè)置類的queryset
屬性來明確如何從數(shù)據(jù)庫中檢索對象,并通過指定serializer_class
來確定用于序列化和反序列化數(shù)據(jù)的序列化器。
然而,需要注意的是,此處的描述中存在一個小錯誤:代碼中的視圖并非繼承自generics.viewsetListViewSet
(因為這樣的類并不存在)。實際上,它可能是繼承自DRF提供的某個泛型視圖集類,例如viewsets.ModelViewSet
,該類結(jié)合了多個通用視圖的行為,并提供了標(biāo)準(zhǔn)的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")
]
關(guān)鍵時刻已經(jīng)到來。首先,讓我們來運行自動化測試。請執(zhí)行以下命令:
(venv)music_service$ python manage.py test
shell中的輸出應(yīng)該與此類似;
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
,然后使用您在項目設(shè)置階段所創(chuàng)建的超級用戶賬號和密碼進行登錄。成功登錄后,您將會看到一個管理界面。
點擊admin界面中的“MUSIC”下的“Songs”,您將會看到一個界面,它可能如下所示:
點擊“ADD SONGS
”按鈕,然后添加幾首歌曲用于測試。完成后,請在瀏覽器中導(dǎo)航到http://127.0.0.1:8000/api/v1/songs
。您將會看到一個界面,它列出了您剛剛添加的所有歌曲,并且以JSON格式呈現(xiàn)。
如果你能看到自己添加的歌曲,那就給自己來個掌聲吧!恭喜你,你的API已經(jīng)成功運行了!
API是后端與前端客戶端之間的約定。API版本控制的功能在于,它允許你對不同客戶端的行為進行更改,并且能夠“優(yōu)雅地”淘汰舊客戶端所使用的舊代碼。因此,為你的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',
}
當(dāng)啟用API版本控制時,request.version
屬性將包含與傳入客戶端請求中請求的版本對應(yīng)的字符串。與下面的示例代碼一樣,我們可以訪問version
屬性并根據(jù)版本號更改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
# ...
到目前為止,我們已經(jīng)見識到使用Django REST framework(DRF)創(chuàng)建API是多么輕松易行。在本教程中,為了保持內(nèi)容的簡潔明了,我只實現(xiàn)了一個API端點,目的是讓您初步了解如何使用這個框架但實際上,利用DRF,您可以構(gòu)建一個功能強大的API。
下表列出了本項目中實現(xiàn)的所有端點的完整清單。如果您想查看API示例的完整實現(xiàn),請訪問我的GitHub倉庫,您可以對其進行分叉(fork),并在學(xué)習(xí)過程中自由地進行嘗試和修改。
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
向資源提交數(shù)據(jù)的表單。如果您正在著手構(gòu)建API,我強烈推薦您查閱以下資源。這些資源是構(gòu)建API時不可或缺的最佳實踐指南。
此外,官方的DRF和Django文檔也是您不可或缺的參考資料。
同時,我還發(fā)現(xiàn)cdrf.co這個資源非常有用。它詳細(xì)闡述了DRF框架中所有類的結(jié)構(gòu)和功能,幫助您更深入地了解DRF的底層實現(xiàn)。
在接下來的第二部分中,我將深入探討DRF中的身份驗證和權(quán)限機制,并展示如何將這些機制應(yīng)用于音樂服務(wù)API端點。
希望這篇文章對您有所幫助。
原文鏈接:https://medium.com/backticks-tildes/lets-build-an-api-with-django-rest-framework-32fcf40231e5