架构
可供机器读取的 [架构] 描述了可通过 API 获得的资源、它们的 URL、它们的表示方式以及它们支持的操作。
— Heroku,Heroku 平台 API 的 JSON 架构
弃用通知
REST 框架内置的 OpenAPI 架构生成支持已弃用,取而代之的是可以提供此功能的第三方软件包。内置支持将移至一个单独的软件包,然后在后续版本中逐步淘汰。
作为全面替代,我们推荐使用 drf-spectacular 软件包。它广泛支持从 REST 框架 API 生成 OpenAPI 3 架构,并提供了自动和可自定义选项。有关详细信息,请参阅 记录您的 API。
API 架构是一个有用的工具,允许一系列用例,包括生成参考文档或驱动可以与您的 API 交互的动态客户端库。
Django REST 框架提供对 OpenAPI 架构自动生成的支持。
概述
架构生成有几个活动部分。值得概述一下
SchemaGenerator
是一个顶级类,负责遍历您配置的 URL 模式,查找APIView
子类,查询它们的架构表示,并编译最终架构对象。AutoSchema
封装了每个视图架构内省所需的所有详细信息。通过schema
属性附加到每个视图。您对AutoSchema
进行子类化以自定义您的架构。generateschema
管理命令允许您离线生成静态架构。- 或者,您可以路由
SchemaView
以动态生成和提供您的架构。 settings.DEFAULT_SCHEMA_CLASS
允许您指定一个AutoSchema
子类作为您项目的默认值。
以下部分将进行更多解释。
生成 OpenAPI 架构
安装依赖项
pip install pyyaml uritemplate inflection
pyyaml
用于将架构生成到基于 YAML 的 OpenAPI 格式中。uritemplate
在内部用于获取路径中的参数。inflection
用于在列表端点中更恰当地使操作复数化。
使用 generateschema
管理命令生成静态架构
如果架构是静态的,则可以使用 generateschema
管理命令
./manage.py generateschema --file openapi-schema.yml
以这种方式生成架构后,可以使用架构生成器无法自动推断的任何其他信息对其进行注释。
你可能希望将 API 架构检入版本控制中,并使用每个新版本对其进行更新,或从网站的静态媒体中提供 API 架构。
使用 SchemaView
生成动态架构
如果你需要动态架构,例如,因为外键选择取决于数据库值,则可以路由一个 SchemaView
,该视图将按需生成和提供架构。
要路由 SchemaView
,请使用 get_schema_view()
帮助器。
在 urls.py
中
from rest_framework.schemas import get_schema_view
urlpatterns = [
# ...
# Use the `get_schema_view()` helper to add a `SchemaView` to project URLs.
# * `title` and `description` parameters are passed to `SchemaGenerator`.
# * Provide view name for use with `reverse()`.
path(
"openapi",
get_schema_view(
title="Your Project", description="API for all things …", version="1.0.0"
),
name="openapi-schema",
),
# ...
]
get_schema_view()
get_schema_view()
帮助器采用以下关键字参数
title
:可用于为架构定义提供描述性标题。description
:较长的描述性文本。version
:API 的版本。-
url
:可用于为架构传递规范基本 URL。schema_view = get_schema_view( title='Server Monitoring API', url='https://www.example.org/api/' )
-
urlconf
:表示要为其生成 API 架构的 URL conf 的导入路径的字符串。这默认为 Django 的ROOT_URLCONF
设置的值。schema_view = get_schema_view( title='Server Monitoring API', url='https://www.example.org/api/', urlconf='myproject.urls' )
-
patterns
:用于将架构自省限制为的 URL 模式列表。如果你只想在架构中公开myproject.api
URLschema_url_patterns = [ path('api/', include('myproject.api.urls')), ] schema_view = get_schema_view( title='Server Monitoring API', url='https://www.example.org/api/', patterns=schema_url_patterns, )
public
:可用于指定架构是否应绕过视图权限。默认为 False
-
generator_class
:可用于指定要传递给SchemaView
的SchemaGenerator
子类。 authentication_classes
:可用于指定将应用于架构端点的身份验证类列表。默认为settings.DEFAULT_AUTHENTICATION_CLASSES
permission_classes
:可用于指定将应用于架构端点的权限类列表。默认为settings.DEFAULT_PERMISSION_CLASSES
。renderer_classes
:可用于传递可用于呈现 API 根端点的渲染器类集。
SchemaGenerator
架构级自定义
from rest_framework.schemas.openapi import SchemaGenerator
SchemaGenerator
是一个类,它遍历路由的 URL 模式列表,请求每个视图的架构,并整理结果 OpenAPI 架构。
通常你不需要自己实例化 SchemaGenerator
,但你可以像这样
generator = SchemaGenerator(title='Stock Prices API')
参数
title
必需:API 的名称。description
:较长的描述性文本。version
:API 的版本。默认为0.1.0
。url
:API 架构的根 URL。除非架构包含在路径前缀下,否则不需要此选项。patterns
:生成架构时要检查的 URL 列表。默认为项目的 URL 配置。urlconf
:生成架构时要使用的 URL 配置模块名称。默认为settings.ROOT_URLCONF
。
为了自定义顶级架构,请对 rest_framework.schemas.openapi.SchemaGenerator
进行子类化,并将子类作为参数提供给 generateschema
命令或 get_schema_view()
帮助函数。
get_schema(self, request=None, public=False)
返回表示 OpenAPI 架构的字典
generator = SchemaGenerator(title='Stock Prices API')
schema = generator.get_schema()
request
参数是可选的,如果你想对生成的架构应用按用户权限,可以使用此参数。
如果你想自定义生成的字典,这是一个很好的重写点。例如,你可能希望向 顶级 info
对象 添加服务条款
class TOSSchemaGenerator(SchemaGenerator):
def get_schema(self, *args, **kwargs):
schema = super().get_schema(*args, **kwargs)
schema["info"]["termsOfService"] = "https://example.com/tos.html"
return schema
AutoSchema
按视图自定义
from rest_framework.schemas.openapi import AutoSchema
默认情况下,视图内省由 AutoSchema
实例执行,可通过 APIView
上的 schema
属性访问。
auto_schema = some_view.schema
AutoSchema
提供了每个视图、请求方法和路径所需的 OpenAPI 元素
- OpenAPI 组件 列表。在 DRF 术语中,这些是描述请求和响应正文的序列化程序映射。
- 描述端点的适当 OpenAPI 操作对象,包括分页、过滤等的路径和查询参数。
components = auto_schema.get_components(...)
operation = auto_schema.get_operation(...)
在编译架构时,SchemaGenerator
会为每个视图、允许的方法和路径调用 get_components()
和 get_operation()
。
注意:组件的自动内省和许多操作参数依赖于 GenericAPIView
的相关属性和方法:get_serializer()
、pagination_class
、filter_backends
等。对于基本的 APIView
子类,由于这个原因,默认内省基本上仅限于 URL 关键字参数路径参数。
AutoSchema
封装了架构生成所需的视图内省。因此,所有架构生成逻辑都保存在一个地方,而不是分散在已经广泛的视图、序列化程序和字段 API 中。
遵循此模式,在自定义架构生成时,尽量不要让架构逻辑泄漏到自己的视图、序列化程序或字段中。你可能会倾向于做类似这样的事情
class CustomSchema(AutoSchema):
"""
AutoSchema subclass using schema_extra_info on the view.
"""
...
class CustomView(APIView):
schema = CustomSchema()
schema_extra_info = ... # some extra info
在这里,AutoSchema
子类在视图中查找 schema_extra_info
。这是可以的(实际上并没有什么害处),但这意味着你的架构逻辑最终会分散在许多不同的地方。
相反,尝试对 AutoSchema
进行子类化,以便 extra_info
不会泄漏到视图中
class BaseSchema(AutoSchema):
"""
AutoSchema subclass that knows how to use extra_info.
"""
...
class CustomSchema(BaseSchema):
extra_info = ... # some extra info
class CustomView(APIView):
schema = CustomSchema()
这种风格稍微冗长一些,但保持了与架构相关的代码的封装。在术语中,它更内聚。它将使你的其他 API 代码更加简洁。
如果某个选项适用于多个视图类,而不是为每个视图创建特定的子类,你可能会发现允许将该选项指定为基本 AutoSchema
子类的 __init__()
关键字参数更方便
class CustomSchema(BaseSchema):
def __init__(self, **kwargs):
# store extra_info for later
self.extra_info = kwargs.pop("extra_info")
super().__init__(**kwargs)
class CustomView(APIView):
schema = CustomSchema(extra_info=...) # some extra info
这样可以节省你为常用选项为每个视图创建自定义子类的麻烦。
并非所有 AutoSchema
方法都公开相关的 __init__()
kwargs,但对于更常用的选项来说,它们确实公开。
AutoSchema
方法
get_components()
生成描述请求和响应正文的 OpenAPI 组件,从序列化器派生其属性。
返回将组件名称映射到生成表示形式的字典。默认情况下,它只包含一对,但你可以覆盖 get_components()
以返回多对,如果你的视图使用多个序列化器。
get_component_name()
从序列化器计算组件的名称。
如果你的 API 具有重复的组件名称,你可能会看到警告。如果是这样,你可以覆盖 get_component_name()
或传递 component_name
__init__()
kwarg(见下文)以提供不同的名称。
get_reference()
返回对序列化器组件的引用。如果你覆盖 get_schema()
,这可能很有用。
map_serializer()
将序列化器映射到其 OpenAPI 表示形式。
大多数序列化器都应该符合标准的 OpenAPI object
类型,但你可能希望覆盖 map_serializer()
以自定义此字段或其他序列化器级别的字段。
map_field()
将各个序列化器字段映射到其架构表示形式。基本实现将处理 Django REST Framework 提供的默认字段。
对于 SerializerMethodField
实例,其架构未知,或者自定义字段子类,你应该覆盖 map_field()
以生成正确的架构
class CustomSchema(AutoSchema):
"""Extension of ``AutoSchema`` to add support for custom field schemas."""
def map_field(self, field):
# Handle SerializerMethodFields or custom fields here...
# ...
return super().map_field(field)
第三方包的作者应该旨在提供一个 AutoSchema
子类,以及一个 mixin,覆盖 map_field()
,以便用户可以轻松地为其自定义字段生成架构。
get_tags()
OpenAPI 按标签对操作进行分组。默认情况下,标签取自路由 URL 的第一路径段。例如,像 /users/{id}/
这样的 URL 将生成标签 users
。
你可以传递一个 __init__()
kwarg 来手动指定标签(见下文),或覆盖 get_tags()
以提供自定义逻辑。
get_operation()
返回描述端点的 OpenAPI 操作对象,包括分页、过滤等路径和查询参数。
与 get_components()
一起,这是视图自省的主要入口点。
get_operation_id()
每个操作都必须有一个唯一的 operationid。默认情况下,operationId
从模型名称、序列化器名称或视图名称中推断出来。operationId 看起来像 "listItems"、"retrieveItem"、"updateItem" 等。按照惯例,operationId
是驼峰式大小写。
get_operation_id_base()
如果您有多个具有相同模型名称的视图,您可能会看到重复的 operationIds。
为了解决这个问题,您可以覆盖 `get_operation_id_base()` 来为 ID 的名称部分提供不同的基础。
get_serializer()
如果视图已实现 `get_serializer()`,则返回结果。
get_request_serializer()
默认情况下返回 `get_serializer()`,但可以覆盖它以区分请求和响应对象。
get_response_serializer()
默认情况下返回 `get_serializer()`,但可以覆盖它以区分请求和响应对象。
AutoSchema.__init__()
kwargs
如果默认生成的数值不合适,AutoSchema
提供许多 `__init__()` kwargs,可用于常见自定义。
可用的 kwargs 是
tags
:指定标签列表。component_name
:指定组件名称。operation_id_base
:指定操作 ID 的资源名称部分。
在视图中声明 `AutoSchema` 实例时,传递 kwargs
class PetDetailView(generics.RetrieveUpdateDestroyAPIView):
schema = AutoSchema(
tags=['Pets'],
component_name='Pet',
operation_id_base='Pet',
)
...
假设一个 `Pet` 模型和 `PetSerializer` 序列化器,此示例中的 kwargs 可能不需要。但是,通常情况下,如果您有多个视图针对同一模型,或有多个视图具有相同名称的序列化器,则需要传递 kwargs。
如果您的视图具有经常需要的相关自定义,您可以为您的项目创建一个基础 `AutoSchema` 子类,它采用额外的 `__init__()` kwargs 来保存每个视图的 `AutoSchema` 子类。