最近在做Restful API的建立,故有些東西先記錄下來,避免日後忘記,所以這邊不會去細講Django的rest-framework與其套件drf_yasg,僅針對一些設定記錄下來.
由於在建立API時,可能因為產品與時間的迭代,會出現好幾個版本的API,但要怎麼明確讓使用者知道使用哪隻API,又可以讓過去已經使用API的人還可以使用舊有的API這就在設計的時候需要思考的,當然設計的方式有很多種,這邊我將只是透過django的路由機制來進行調整.
1.規劃想法
未來使用者,使用的API URL為類似
1 2 3 |
http://localhost:8888/api/v1/action1 http://localhost:8888/api/v2/action1 |
所以需要產生v1與v2版本的API,路由分別為
1 2 3 4 5 |
v1/action1 v1/action2 v2/action1 v2/action2 |
2.為了避免錯亂,我先將專案架構列出來會比較清楚(注意紅色區塊即可)
3.先設定一下v1的路由(api/urls.py)
1 2 3 4 5 6 |
from django.urls import path from .views.v1 import views_v1 urlpatterns = [ path('v1/action1', views_v1.action1.as_view(), name='v1action1'), path('v1/action2', views_v1.action2.as_view(), name='v1action2'), ] |
4.記得要把view也加上喔!(api/views/v1/views_v1.py),因為這邊不是在說明drf_yasg,所以這邊我就不特別說明views怎麼寫
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
from drf_yasg.utils import swagger_auto_schema from rest_framework.generics import GenericAPIView class action1(GenericAPIView): #swagger_tags = ["v1"] @swagger_auto_schema( responses='', operation_summary='v1 action1', operation_description='POST v1/action1', ) def post(self, request, *args, **kwargs): pass class action1(GenericAPIView): #swagger_tags = ["v1"] @swagger_auto_schema( responses='', operation_summary='v1 action2', operation_description='POST v1/action2', ) def post(self, request, *args, **kwargs): pass |
5.測試一下
6.基本上v1版本的API就建立好了,但由步驟4可以注意紅框的地方,套件會自動帶出Base URL,筆者測試的時候,以為如果建立好v2會不會Base URL都停留在/api/v1上?
7.讓我們繼續看下去,將v2版本的API也設定上去吧,先加上路由(api/urls.py)
1 2 3 4 5 6 7 8 9 |
from django.urls import path from .views.v1 import views_v1 from .views.v2 import views_v2 urlpatterns = [ path('v1/action1', views_v1.action1.as_view(), name='v1action1'), path('v1/action2', views_v1.action2.as_view(), name='v1action2'), path('v2/action1', views_v2.action1.as_view(), name='v2action1'), path('v2/action2', views_v2.action2.as_view(), name='v2action2') ] |
8.記得要把view也加上喔!(api/views/v2/views_v2.py),這次是加v2別搞錯噢!!因為這邊不是在說明drf_yasg,所以這邊我就不特別說明views怎麼寫
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
from drf_yasg.utils import swagger_auto_schema from rest_framework.generics import GenericAPIView class action1(GenericAPIView): #swagger_tags = ["v2"] @swagger_auto_schema( responses='', operation_summary='v2 action1', operation_description='POST v2/action1', ) def post(self, request, *args, **kwargs): pass class action1(GenericAPIView): #swagger_tags = ["v2"] @swagger_auto_schema( responses='', operation_summary='v2 action2', operation_description='POST v2/action2', ) def post(self, request, *args, **kwargs): pass |
9.來看看變成如何!神奇的事情發生了,剛剛步驟6筆者擔心的地方,套件自己改變了,會自動轉為/api這樣就不會錯亂了!
10.後記
-採用版本
1 2 3 4 |
python 3.7.4 django 3.2.3 djangorestframework 3.12.2 drf-yasg 1.20.0 |
-可以看到步驟9系統會依據版本幫您分類,如果沒有出現可能是因為套件版本,可以這麼做
A.在專案底下建立一個資料夾config,裡面建立一個swagger.py,覆寫SwaggerAutoSchema
1 2 3 4 5 6 7 8 9 10 11 12 |
from drf_yasg.inspectors import SwaggerAutoSchema class CustomSwaggerAutoSchema(SwaggerAutoSchema): def get_tags(self, operation_keys=None): operation_keys = operation_keys or self.operation_keys tags = self.overrides.get('tags') if not tags: tags = [operation_keys[0]] if hasattr(self.view, "swagger_tags"): tags = self.view.swagger_tags return tags |
B.在每個view加入版本資訊,以api/v1/views_v1.py為例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
from drf_yasg.utils import swagger_auto_schema from rest_framework.generics import GenericAPIView class action1(GenericAPIView): swagger_tags = ["v1"] #主要加入此行產生聚合效果 @swagger_auto_schema( responses='', operation_summary='v1 action1', operation_description='POST v1/action1', ) def post(self, request, *args, **kwargs): pass class action1(GenericAPIView): swagger_tags = ["v1"] #主要加入此行產生聚合效果 @swagger_auto_schema( responses='', operation_summary='v1 action2', operation_description='POST v1/action2', ) def post(self, request, *args, **kwargs): pass |
C.修改專案setting.py,加入以下,重啟專案應該就會分類了
1 2 3 |
SWAGGER_SETTINGS = { 'DEFAULT_AUTO_SCHEMA_CLASS': 'config.swagger.CustomSwaggerAutoSchema', } |
11.連文件都可以依據版本分類喔!
12.補充
-後來在測試會不會依據版本分類,發現只有v1版的時後,系統會將api每一隻拆開,但當有v2後,就會聚合v1一組v2一組,不需要再加上步驟10,除非想要只有v1也產生聚合效果才要加!
–只有v1的樣子
–只有v1又想要有聚合效果
–v1與v2同時存在