自定義 drf-yasg 的 Swagger 文檔— 以 GET、POST、檔案上傳為例

Jo-Yu Liao
10 min readMay 11, 2020

--

簡介如何自訂義 Django REST framework 生成 swagger 的套件 drf-yasg 的文檔。

本篇主要介紹如何自訂義 drf-yasg 的 swagger 文檔,如果對 drf-yasg 不熟悉可以參考此篇:用 Django REST Framework 撰寫 RESTful API 並生成 Swagger 文檔,本篇的 code 可以參考這個 Pull Request

以下的操作都是會用到 drf_yasg 的裝飾器 swagger_auto_schemaswagger_auto_schema 的功用依照 drf_yasg 的定義為:

Decorate a view method to customize the Operation object generated from it.

所以我們需要在預修改的 view.py 引入該裝飾器,就可以準備自定義 Swagger 囉!

from drf_yasg.utils import swagger_auto_schema

一、為 API Operation(如 GET, POST, PATCH, DELETE)加摘要和說明

首先在 API 的 operation 上面加上裝飾器,然後我們就可以設置 swagger_auto_schemaoperation_summary設置摘要,還有用operation_description撰寫說明。

@swagger_auto_schema(
operation_summary='我是摘要',
operation_description='我是說明',
)

比方說:

# swagger
from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi
# other packages
from rest_framework.generics import GenericAPIView
from user.serializers import UserSerializer

class UsersView(GenericAPIView):
serializer_class = UserSerializer @swagger_auto_schema(
operation_summary='我是 GET 的摘要',
operation_description='我是 GET 的說明',
)
def get(self, request, *args, **krgs):
略 ...
@swagger_auto_schema(
operation_summary='我是 POST 的摘要',
operation_description='我是 POST 的說明',
)
def post(self, request, *args, **krgs):
略 ...

就可以得到下面的結果:

operation_summary
operation_description

二、為 API Operation(如 GET, POST, PATCH, DELETE)客製化參數

1. 自定義 POST 請求

如果你有用 Serializer,則 drf_yasg 默認會用 serializers.py 定義的 field,比方說我有一個 User 的 model,裡面有 id, email, name 三個 fields:

from django.db import models


class User(models.Model):
id = models.AutoField(auto_created=True, primary_key=True)
email = models.EmailField(unique=True)
name = models.CharField(max_length=100)

因為我在 serializer 寫 field='__all__',所以默認在 POST 請求的時候會用除了auto_created 的 id 以外的 field (emial, name)

from user.models import User
from rest_framework import serializers

class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = '__all__'
default data

如果不希望用 class 的 serializer,可以用 request_body 指定其他 serializer:

@swagger_auto_schema(
operation_summary='我是 POST 的摘要',
request_body=其他 Serializer
)

如果希望自定義參數,比如我只想要用戶填 name,可以將 openapi.Schema賦值給 request_body

@swagger_auto_schema(
operation_summary='我是 POST 的摘要',
request_body=openapi.Schema(
type=openapi.TYPE_OBJECT,
properties={
'name': openapi.Schema(
type=openapi.TYPE_STRING,
description='User Name'
)
}
)
)

就可以達成下面的效果囉:

自定義 POST 參數

2. 自定義 GET 請求

如果希望自定義 GET 請求的參數呢?需要用 manual_parameters,比方說我希望依照 name 查詢 API,就可以這樣寫:

@swagger_auto_schema(
operation_summary='我是 GET 的摘要',
manual_parameters=[
openapi.Parameter(
name='name',
in_=openapi.IN_QUERY,
description='User Name',
type=openapi.TYPE_STRING
)
]
)

說明一下參數的意義:

name:參數名

in_:表示參數位於 request 的哪,比如:

  1. openapi.IN_BODY,參數在 request 的 body,例如 POST 請求。
  2. openapi.IN_QUERY,參數在 request 的 quey,例如 user/?name=123。
  3. openapi.IN_FORM,參數在 request 的 form 表單,例如檔案上傳。
  4. openapi.IN_PATH,參數在 request 的 path,比方說 /user/<id>/

type:參數的型別,如:openapi.TYPE_STRINGopenapi.TYPE_NUMBERopenapi.TYPE_INTEGERopenapi.TYPE_BOOLEANopenapi.TYPE_ARRAYopenapi.TYPE_FILE等,更多資訊可參考官方文檔

自定義 GET 請求的參數

2. 自定義 Form 表單請求

Form 表單稍微複雜一點,需要指定 View 的 parser_class為 FormParser如果還有其他參數要一起提交,則要加上MultiPartParser不然會有以下錯誤:

Unsupported media type \”multipart/form-data; boundary= — — WebKitFormBoundaryU5zgTtpr7NV7zNFt\” in request.”

所以要改成:

from rest_framework.parsers import (
FormParser,
MultiPartParser
)
其他 packages 略 ...
class UsersView(GenericAPIView): parser_classes = (FormParser, MultiPartParser) @swagger_auto_schema(
operation_summary='我是 POST 的摘要',
operation_description='我是 POST 的說明',
manual_parameters=[
openapi.Parameter(
name='image',
in_=openapi.IN_FORM,
description='Image',
type=openapi.TYPE_FILE
),
]
)
def post(self, request, *args, **krgs):
略...

就可以達到下面結果囉!

等等那個 email 跟 name 是怎麼肥事??原因是會默認拿 Serializer 的 field QQ 如果這些參數不需要用戶填寫可考慮設 readonly。

三、API 已棄用

如果要標註某些 API 已棄用,只需要加上 depracated=True即可,如:

class UsersView(GenericAPIView):    @swagger_auto_schema(
operation_summary='我是 POST 的摘要',
operation_description='我是 POST 的說明',
depracated=True
)
def post(self, request, *args, **krgs):
略...

就有下面的效果:

以上是如何自訂義 Django REST framework 生成 swagger 的套件 drf-yasg 的文檔的簡介,感謝閱讀。

--

--