1. 程式人生 > >django-rest-swagger

django-rest-swagger

前提工作

pip3 install --user django>=2.0.0
pip3 install --user django-rest-swagger

安裝完成之後,建立一個django專案
第一步:修改setting配置如下

INSTALLED_APPS = [
'app.apps.AppConfig',
'rest_framework',
'rest_framework_swagger',
]

並新增

SWAGGER_SETTINGS = {
# 基礎樣式
'SECURITY_DEFINITIONS': {
"basic":{
'type': 'basic'
}
},

# 如果需要登入才能夠檢視介面文件, 登入的連結使用restframework自帶的.

'LOGIN_URL': 'rest_framework:login',
'LOGOUT_URL': 'rest_framework:logout',
# 'DOC_EXPANSION': None,
# 'SHOW_REQUEST_HEADERS':True,
# 'USE_SESSION_AUTH': True,
# 'DOC_EXPANSION': 'list',
# 介面文件中方法列表以首字母升序排列
'APIS_SORTER': 'alpha',
# 如果支援json提交, 則介面文件中包含json輸入框
'JSON_EDITOR': True,
# 方法列表字母排序
'OPERATIONS_SORTER': 'alpha',
'VALIDATOR_URL': None,
}

配置完成,接下來要編寫自定義swagger介面文件頁面
在urls.py介面文件中來源from rest_framework.schemas import get_schema_view
具體如

from django.conf.urls import url,include
from django.contrib import admin
from rest_framework import routers
from app import views

# 路由

router = routers.DefaultRouter()
router.register(r'users',views.UserViewSet,base_name='user')
router.register(r'groups',views.GroupViewSet,base_name='group')

# 重要的是如下三行

from rest_framework.schemas import get_schema_view
from rest_framework_swagger.renderers import SwaggerUIRenderer, OpenAPIRenderer
schema_view = get_schema_view(title='Users API', renderer_classes=[OpenAPIRenderer, SwaggerUIRenderer])
urlpatterns = [
# swagger介面文件路由
# url(r'^docs/', schema_view, name="docs"), 注:此條docs用到上面的router
url(r'^docs/', views.SwaggerSchemaView.as_view(), name='apiDocs'), # 此條是自定義,本篇主要使用此條
url(r'^admin/', admin.site.urls),
url(r'^',include(router.urls)),


# drf登入

url(r'^api-auth/',include('rest_framework.urls',namespace='rest_framework')),
url(r'^api/getjson', views.ReturnJson.as_view()),
]

檢視原始碼, 繼承schema, 返回schema的子類即可.
接下來編寫自己的schema,可以重新起一個檔名。

from django.http import HttpResponse, JsonResponse
from django.contrib.auth.models import User,Group
from rest_framework import viewsets
from app.serializer import UserSerializer,GroupSerializer
from rest_framework.response import Response
from .serializer import UserBaseSerializer
from rest_framework.permissions import AllowAny
from rest_framework.schemas import SchemaGenerator
from rest_framework.schemas.generators import LinkNode, insert_into
from rest_framework.renderers import CoreJSONRenderer
from rest_framework_swagger import renderers
from rest_framework.views import APIView
import coreapi
from django.http import QueryDict
from rest_framework.request import Request
class MySchemaGenerator(SchemaGenerator):
def get_links(self, request=None):
# from rest_framework.schemas.generators import LinkNode,
links = LinkNode()

paths = []
view_endpoints = []
for path, method, callback in self.endpoints:
view = self.create_view(callback, method, request)
path = self.coerce_path(path, method, view)
paths.append(path)
view_endpoints.append((path, method, view))

# Only generate the path prefix for paths that will be included
if not paths:
return None
prefix = self.determine_path_prefix(paths)

for path, method, view in view_endpoints:
if not self.has_view_permissions(path, method, view):
continue
link = view.schema.get_link(path, method, base_url=self.url)
# 新增下面這一行方便在views編寫過程中自定義引數.
link._fields += self.get_core_fields(view)

subpath = path[len(prefix):]
keys = self.get_keys(subpath, method, view)

# from rest_framework.schemas.generators import LinkNode, insert_into
insert_into(links, keys, link)

return links

# 從類中取出我們自定義的引數, 交給swagger 以生成介面文件.
def get_core_fields(self, view):
return getattr(view, 'coreapi_fields', ())

class SwaggerSchemaView(APIView):
_ignore_model_permissions = True
exclude_from_schema = True

# from rest_framework.permissions import AllowAny
permission_classes = [AllowAny]
# from rest_framework_swagger import renderers
# from rest_framework.renderers import *
renderer_classes = [
CoreJSONRenderer,
renderers.OpenAPIRenderer,
renderers.SwaggerUIRenderer
]
def get(self, request):
generator = MySchemaGenerator(title='xxxxx',
description='''xxxxx''')

schema = generator.get_schema(request=request)

# from rest_framework.response import Response
return Response(schema)

然後啟動
上面的程式碼自定義了一個swagger頁面, 加入了自定義引數的方法, 設定了訪問許可權(AllowAny), 添加了title和description,
原理, 其實就是繼承父類, 重寫方法以覆蓋父類中的方法, 修改子類中overwrite的方法以新增我們想要的內容.
上面的程式碼其實寫在哪裡都可以, 找得到就行,我一般寫在views.py 檔案中和其他介面放在一起, 畢竟 http://xxxxx/docs/ 和/api/getjson 這樣的介面一樣都返回一個檢視.
需要注意的是一般用的是docs,而api-auth/就是為'LOGIN_URL': 'rest_framework:login','LOGOUT_URL': 'rest_framework:logout'準備的. 因為有時我們需要讓介面文件登入之後才能夠被看到。

一切準備就緒,接下來就開始自定義介面文件了。在上面的urls.py中的 api/getjson就是,然後開始編寫。可以和上面的schema放在一個資料夾裡,個人習慣放在一起

# Create your views here.

# class UserViewSet(viewsets.ModelViewSet):
# '''檢視,編輯使用者的介面'''
# queryset = User.objects.all().order_by('-date_joined')
# serializer_class = UserSerializer
#
# class GroupViewSet(viewsets.ModelViewSet):
# '''檢視,編輯組的介面'''
# queryset = Group
# serializer_class = GroupSerializer

def DocParam(name="default", location="query",
required=True, description=None, type="string",
*args, **kwargs):
# 頁面編輯顯示輸入引數
return coreapi.Field(name=name, location=location,
required=required, description=description,
type=type)

def get_parameter_dic(request, *args, **kwargs):
# 處理自定義介面傳過來的引數值
if isinstance(request, Request) == False:
    return {}

query_params = request.query_params
if isinstance(query_params, QueryDict):
    query_params = query_params.dict()
    result_data = request.data
if isinstance(result_data, QueryDict):
r   esult_data = result_data.dict()

if query_params != {}:
    query_params
else:
    return result_data

class ReturnJson(APIView):
    coreapi_fields = (
    DocParam("token"),
    DocParam('id'),
    )

    def get(self, request, *args, **kwargs):
        params = get_parameter_dic(request)
        print(params)
        return JsonResponse(data=params)

    def post(self, request, *args, **kwargs):
        params = get_parameter_dic(request)
        return JsonResponse(data=params)

    def put(self, request, *args, **kwargs):
        params = get_parameter_dic(request)
        return JsonResponse(data=params)  

然後重啟,請求訪問測試結果如圖。