API schema 是一個很是有用的工具,它容許一系列用例,包括生成參考文檔,或者驅動能夠與 API 交互的動態客戶端庫。python
你須要安裝 coreapi
軟件包才能爲 REST framework 添加 schema 支持。git
pip install coreapi
複製代碼
REST framework 使用 Core API 以便以獨立於格式的表示對 schema 信息建模。這些信息能夠被渲染成各類不一樣的 schema 格式,或者用於生成 API 文檔。github
在使用 Core API 時,schema 表示爲 Document
,它是有關 API 信息的頂級容器對象。可用的 API 交互使用 Link
對象表示。每一個連接都包含一個 URL,HTTP 方法,而且可能包含一個 Field
實例列表,它描述了 API 端點能夠接受的任何參數。Link
和 Field
實例還可能包含描述,容許將 API schema 渲染到用戶文檔中。django
如下是包含單個搜索端點的 API 說明示例:json
coreapi.Document(
title='Flight Search API',
url='https://api.example.org/',
content={
'search': coreapi.Link(
url='/search/',
action='get',
fields=[
coreapi.Field(
name='from',
required=True,
location='query',
description='City name or airport code.'
),
coreapi.Field(
name='to',
required=True,
location='query',
description='City name or airport code.'
),
coreapi.Field(
name='date',
required=True,
location='query',
description='Flight date in "YYYY-MM-DD" format.'
)
],
description='Return flight availability and prices.'
)
}
)
複製代碼
爲了呈如今 HTTP 響應中,必須將內部表示渲染爲響應中使用的實際字節。api
Core JSON 被設計爲與 Core API 一塊兒使用的規範格式。REST framework 包含用於處理此媒體類型的渲染器類,該渲染器類可用做 renderers.CoreJSONRenderer
。bash
其餘 schema 格式(如 Open API(「Swagger」),JSON HyperSchema 或 API Blueprint)也能夠經過實現處理將 Document
實例轉換爲字符串表示形式的自定義渲染器類來支持。app
若是有一個 Core API 編解碼器包支持將編碼格式化爲你要使用的格式,則可使用編解碼器來實現渲染器類。ide
例如,openapi_codec
包提供對 Open API(「Swagger」)格式的編碼或解碼支持:
from rest_framework import renderers
from openapi_codec import OpenAPICodec
class SwaggerRenderer(renderers.BaseRenderer):
media_type = 'application/openapi+json'
format = 'swagger'
def render(self, data, media_type=None, renderer_context=None):
codec = OpenAPICodec()
return codec.dump(data)
複製代碼
值得指出的是,Core API 也能夠用來模擬超媒體響應,它爲 API schema 提供了另外一種交互風格。
經過 API schema,整個可用接口做爲單個端點呈如今前端。而後,對各個 API 端點的響應一般會以普通數據的形式呈現,而不會在每一個響應中包含任何進一步的交互。
使用超媒體,客戶端會看到包含數據和可用交互的文檔。每次交互都會生成一個新文檔,詳細說明當前狀態和可用交互。
REST framework 包含用於自動生成 schema 的功能,或者容許你明確指定。
要手動指定 schema,請建立一個 Core API Document
,與上例相似。
schema = coreapi.Document(
title='Flight Search API',
content={
...
}
)
複製代碼
自動 schema 生成由 SchemaGenerator
類提供。
SchemaGenerator
處理路由 URL pattterns 列表並編譯適當結構化的 Core API 文檔。
基本用法只是爲 schema 提供標題並調用 get_schema()
:
generator = schemas.SchemaGenerator(title='Flight Search API')
schema = generator.get_schema()
複製代碼
默認狀況下,查看自省是由可經過 APIView
上的 schema
屬性訪問的 AutoSchema
實例執行的。這爲視圖,請求方法和路徑提供了適當的 Core API Link
對象:
auto_schema = view.schema
coreapi_link = auto_schema.get_link(...)
複製代碼
(在編譯模式時,SchemaGenerator
爲每一個視圖,容許的方法和路徑調用 view.schema.get_link()
。)
注意: 對於基本的 APIView
子類,默認內省本質上僅限於 URL kwarg 路徑參數。對於包含全部基於類的視圖的 GenericAPIView
子類,AutoSchema
將嘗試自省列化器,分頁和過濾器字段,並提供更豐富的路徑字段描述。(這裏的關鍵鉤子是相關的 GenericAPIView
屬性和方法:get_serializer
,pagination_class
,filter_backends
等。)
要自定義 Link
生成,你能夠:
1)使用 manual_fields
kwarg 在你的視圖上實例化 AutoSchema
:
from rest_framework.views import APIView
from rest_framework.schemas import AutoSchema
class CustomView(APIView):
...
schema = AutoSchema(
manual_fields=[
coreapi.Field("extra_field", ...),
]
)
複製代碼
這容許擴展最多見的狀況而不須要子類化。
2)提供具備更復雜定製的 AutoSchema
子類:
from rest_framework.views import APIView
from rest_framework.schemas import AutoSchema
class CustomSchema(AutoSchema):
def get_link(...):
# Implement custom introspection here (or in other sub-methods)
class CustomView(APIView):
...
schema = CustomSchema()
複製代碼
這提供了對查看內省的徹底控制。
3)在你的視圖上實例化 ManualSchema
,顯式爲視圖提供 Core API Fields
:
from rest_framework.views import APIView
from rest_framework.schemas import ManualSchema
class CustomView(APIView):
...
schema = ManualSchema(fields=[
coreapi.Field(
"first_field",
required=True,
location="path",
schema=coreschema.String()
),
coreapi.Field(
"second_field",
required=True,
location="path",
schema=coreschema.String()
),
])
複製代碼
這容許手動指定某些視圖的 schema,同時在別處保持自動生成。
經過將 schema
設置爲 None
,你能夠禁用視圖的 schema 生成:
class CustomView(APIView):
...
schema = None # Will not appear in schema
複製代碼
有幾種不一樣的方式能夠將 schema 視圖添加到你的 API 中,具體取決於你須要的內容。
在你的項目中包含 schema 的最簡單方法是使用 get_schema_view()
函數。
from rest_framework.schemas import get_schema_view
schema_view = get_schema_view(title="Server Monitoring API")
urlpatterns = [
url('^$', schema_view),
...
]
複製代碼
添加視圖後,你將可以經過 API 請求來檢索自動生成的 schema 定義。
$ http http://127.0.0.1:8000/ Accept:application/coreapi+json
HTTP/1.0 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/vnd.coreapi+json
{
"_meta": {
"title": "Server Monitoring API"
},
"_type": "document",
...
}
複製代碼
get_schema_view()
的參數是:
title
可用於爲 schema 定義提供描述性標題。
url
可用於爲 schema 傳遞規範 URL。
schema_view = get_schema_view(
title='Server Monitoring API',
url='https://www.example.org/api/'
)
複製代碼
urlconf
表示要爲其生成 API schema 的 URL conf 的導入路徑的字符串。這默認爲 Django 的 ROOT_URLCONF setting 的值。
schema_view = get_schema_view(
title='Server Monitoring API',
url='https://www.example.org/api/',
urlconf='myproject.urls'
)
複製代碼
renderer_classes
可用於傳遞渲染 API 根端點的渲染器類列表。
from rest_framework.schemas import get_schema_view
from rest_framework.renderers import CoreJSONRenderer
from my_custom_package import APIBlueprintRenderer
schema_view = get_schema_view(
title='Server Monitoring API',
url='https://www.example.org/api/',
renderer_classes=[CoreJSONRenderer, APIBlueprintRenderer]
)
複製代碼
patterns
將 schema 內省限定爲 url patterns 列表。若是你只想將 myproject.api
url 公開在 schema 中:
schema_url_patterns = [
url(r'^api/', include('myproject.api.urls')),
]
schema_view = get_schema_view(
title='Server Monitoring API',
url='https://www.example.org/api/',
patterns=schema_url_patterns,
)
複製代碼
generator_class
可用於指定要傳遞給 SchemaView
的 SchemaGenerator
子類。
authentication_classes
可用於指定將應用於 schema 端點的認證類列表。默認爲 settings.DEFAULT_AUTHENTICATION_CLASSES
permission_classes
可用於指定將應用於 schema 端點的權限類列表。默認爲 settings.DEFAULT_PERMISSION_CLASSES
若是你須要比 get_schema_view()
快捷方式更多的控制權,那麼你能夠直接使用 SchemaGenerator
類來自動生成 Document
實例,並從視圖中返回該實例。
此選項使你能夠靈活地設置 schema 端點,並使用你想要的任何行爲。例如,你能夠將不一樣的權限,限流或身份驗證策略應用於 schema 端點。
如下是使用 SchemaGenerator
和視圖一塊兒返回 schema 的示例。
views.py:
from rest_framework.decorators import api_view, renderer_classes
from rest_framework import renderers, response, schemas
generator = schemas.SchemaGenerator(title='Bookings API')
@api_view()
@renderer_classes([renderers.CoreJSONRenderer])
def schema_view(request):
schema = generator.get_schema(request)
return response.Response(schema)
複製代碼
urls.py:
urlpatterns = [
url('/', schema_view),
...
]
複製代碼
你也能夠爲不一樣的用戶提供不一樣的 schema,具體取決於他們擁有的權限。這種方法能夠用來確保未經身份驗證的請求以不一樣的模式呈現給已驗證的請求,或者確保 API 的不一樣部分根據角色對不一樣用戶可見。
爲了呈現一個 schema,其中包含由用戶權限過濾的端點,你須要將 request
參數傳遞給 get_schema()
方法,以下所示:
@api_view()
@renderer_classes([renderers.CoreJSONRenderer])
def schema_view(request):
generator = schemas.SchemaGenerator(title='Bookings API')
return response.Response(generator.get_schema(request=request))
複製代碼
自動生成方法的替代方法是經過在代碼庫中聲明 Document
對象來明確指定 API schema 。這樣作會多一點工做,但確保你徹底控制 schema 表示。
import coreapi
from rest_framework.decorators import api_view, renderer_classes
from rest_framework import renderers, response
schema = coreapi.Document(
title='Bookings API',
content={
...
}
)
@api_view()
@renderer_classes([renderers.CoreJSONRenderer])
def schema_view(request):
return response.Response(schema)
複製代碼
最後的選擇是使用 Core JSON 或 Open API 等可用格式之一將你的 API schema 編寫爲靜態文件。
而後你能夠:
Core API
加載的 schema 定義,而後根據客戶端請求將其渲染爲多種可用格式之一。API schemas 的一個常見用法是使用它們來構建文檔頁面。
REST framework 中的 schema 生成使用文檔字符串來自動填充 schema 文檔中的描述。
這些描述將基於:
一個 APIView
,帶有明確的方法文檔字符串。
class ListUsernames(APIView):
def get(self, request):
""" Return a list of all user names in the system. """
usernames = [user.username for user in User.objects.all()]
return Response(usernames)
複製代碼
一個 ViewSet
,帶有一個明確的 action 文檔字符串。
class ListUsernames(ViewSet):
def list(self, request):
""" Return a list of all user names in the system. """
usernames = [user.username for user in User.objects.all()]
return Response(usernames)
複製代碼
類文檔字符串中帶有 action 的通用視圖,使用單行樣式。
class UserList(generics.ListCreateAPIView):
""" get: List all the users. post: Create a new user. """
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = (IsAdminUser,)
複製代碼
使用多行樣式的類文檔字符串中帶有 action 的通用視圖集。
class UserViewSet(viewsets.ModelViewSet):
""" API endpoint that allows users to be viewed or edited. retrieve: Return a user instance. list: Return all users, ordered by most recently joined. """
queryset = User.objects.all().order_by('-date_joined')
serializer_class = UserSerializer
複製代碼
一個遍歷路由 URL patterns 列表的類,爲每一個視圖請求 schema 並整理生成的 CoreAPI 文檔。
一般你會用一個參數實例化 SchemaGenerator
,以下所示:
generator = SchemaGenerator(title='Stock Prices API')
複製代碼
參數:
title
必需 - API 的名稱。url
- API schema 的 root URL。除非 schema 包含在路徑前綴下,不然此選項不是必需的。patterns
- 生成 schema 時要檢查的 URL 列表。默認爲項目的 URL conf。urlconf
- 生成 schema 時使用的 URL conf 模塊名稱。 默認爲 settings.ROOT_URLCONF
.返回表示 API schema 的 coreapi.Document
實例。
@api_view
@renderer_classes([renderers.CoreJSONRenderer])
def schema_view(request):
generator = schemas.SchemaGenerator(title='Bookings API')
return Response(generator.get_schema())
複製代碼
request
參數是可選的,若是你但願將每一個用戶的權限應用於生成的 schema ,則可使用該參數。
返回一個嵌套的字典,其中包含在 API schema 中的全部連接。
若是要修改生成的 schema 的結構,重寫該方法很合適,由於你可使用不一樣的佈局構建新的字典。
一個處理 schema 生成的個別視圖內省的類。
AutoSchema
經過 schema
屬性附加到 APIView
。
AutoSchema
構造函數接受一個關鍵字參數 manual_fields
。
manual_fields
: 將添加到生成的字段的 coreapi.Field
實例 list
。具備匹配名稱的生成字段將被覆蓋。
class CustomView(APIView):
schema = AutoSchema(manual_fields=[
coreapi.Field(
"my_extra_field",
required=True,
location="path",
schema=coreschema.String()
),
])
複製代碼
對於經過繼承 AutoSchema
來自定義 schema 生成。
class CustomViewSchema(AutoSchema):
""" Overrides `get_link()` to provide Custom Behavior X """
def get_link(self, path, method, base_url):
link = super().get_link(path, method, base_url)
# Do something to customize link here...
return link
class MyView(APIView):
schema = CustomViewSchema()
複製代碼
如下方法可覆蓋。
返回與給定視圖相對應的 coreapi.Link
實例。
這是主要的入口點。若是你須要爲特定視圖提供自定義行爲,則能夠覆蓋此內容。
返回用做連接描述的字符串。默認狀況下,這基於上面的 「做爲文檔的 Schemas」 action 中描述的視圖文檔字符串。
與給定視圖交互時返回一個字符串,以指定任何請求主體的編碼。 例如 'application/json'
。可能會返回一個空白字符串,以便查看不須要請求主體的視圖。
返回 coreapi.Link()
實例列表。用於 URL 中的每一個路徑參數。
返回 coreapi.Link()
實例列表。用於視圖使用的序列化類中的每一個字段。
返回 coreapi.Link()
實例列表,該列表由 get_schema_fields()
方法返回給視圖使用的分頁類。
返回 coreapi.Link()
實例列表,該列表是由視圖所使用的過濾器類的 get_schema_fields()
方法返回的。
返回 coreapi.Field()
實例列表以添加或替換生成的字段。默認爲(可選)傳遞給 AutoSchema
構造函數的 manual_fields
。
能夠經過 path
或 method
覆蓋自定義 manual field。例如,每一個方法的調整可能以下所示:
def get_manual_fields(self, path, method):
"""Example adding per-method fields."""
extra_fields = []
if method=='GET':
extra_fields = # ... list of extra fields for GET ...
if method=='POST':
extra_fields = # ... list of extra fields for POST ...
manual_fields = super().get_manual_fields(path, method)
return manual_fields + extra_fields
複製代碼
實用的 staticmethod
。封裝邏輯以經過 Field.name
添加或替換列表中的字段。可能會被覆蓋以調整替換標準。
容許手動爲 schema 提供 coreapi.Field
實例的列表,以及一個可選的描述。
class MyView(APIView):
schema = ManualSchema(fields=[
coreapi.Field(
"first_field",
required=True,
location="path",
schema=coreschema.String()
),
coreapi.Field(
"second_field",
required=True,
location="path",
schema=coreschema.String()
),
]
)
複製代碼
ManualSchema
構造函數有兩個參數:
fields
: coreapi.Field
實例列表。必需。
description
: 字符串描述。可選的。
本文檔簡要介紹了用於表示 API schema 的 coreapi
包內的組件。
請注意,這些類是從 coreapi
包導入的,而不是從 rest_framework
包導入的。
表示 API schema 的容器。
title
API 的名稱。
url
API 的規範 URL。
content
一個字典,包含 schema 的 Link
對象。
爲了向 schema 提供更多結構,content
字典能夠嵌套,一般是二層。例如:
content={
"bookings": {
"list": Link(...),
"create": Link(...),
...
},
"venues": {
"list": Link(...),
...
},
...
}
複製代碼
表明一個單獨的 API 端點。
url
端點的 URL。多是一個 URI 模板,例如 /users/{username}/
。
action
與端點關聯的 HTTP 方法。請注意,支持多個 HTTP 方法的 url 應該對應於每一個 HTTP 方法的單個連接。
fields
Field
實例列表,描述輸入上的可用參數。
description
對端點的含義和用途的簡短描述。
表示給定 API 端點上的單個輸入參數。
name
輸入的描述性名稱。
required
boolean 值,表示客戶端是否須要包含值,或者參數是否能夠省略。
location
肯定如何將信息編碼到請求中。應該是如下字符串之一:
"path"
包含在模板化的 URI 中。例如,/products/{product_code}/
的 url
值能夠與 "path"
字段一塊兒使用,以處理 URL 路徑中的 API 輸入,例如 /products/slim-fit-jeans/
。
這些字段一般與項目 URL conf 中的命名參數對應。
"query"
包含爲 URL 查詢參數。例如 ?search=sale
。一般用於 GET
請求。
這些字段一般與視圖上的分頁和過濾控件相對應。
"form"
包含在請求正文中,做爲 JSON 對象或 HTML 表單的單個 item。例如 {"colour": "blue", ...}
。一般用於POST
,PUT
和 PATCH
請求。多個 "form"
字段可能包含在單個連接上。
這些字段一般與視圖上的序列化類字段相對應。
"body"
包含完整的請求主體。一般用於 POST
, PUT
和 PATCH
請求。連接上不得存在超過一個 "body"
字段。不能與 "form"
字段一塊兒使用。
這些字段一般對應於使用 ListSerializer
來驗證請求輸入或使用文件上載的視圖。
encoding
"application/json"
JSON編碼的請求內容。對應於使用 JSONParser
的視圖。僅在 Link
中包含一個或多個 location="form"
字段或單個 location="body"
字段時有效。
"multipart/form-data"
Multipart 編碼的請求內容。對應於使用 MultiPartParser
的視圖。僅在 Link
中包含一個或多個 location="form"
字段時有效。
"application/x-www-form-urlencoded"
URL encode 的請求內容。對應於使用 FormParser
的視圖。僅在 Link
中包含一個或多個 location="form"
字段時有效。
"application/octet-stream"
二進制上傳請求內容。對應於使用 FileUploadParser
的視圖。僅在 Link
中包含 location="body"
字段時有效。
description
對輸入字段的含義和用途的簡短描述。