289 lines
14 KiB
Python
289 lines
14 KiB
Python
from contextlib import contextmanager
|
|
from typing import Any, Dict
|
|
|
|
from django.conf import settings
|
|
from rest_framework.settings import APISettings, perform_import
|
|
|
|
SPECTACULAR_DEFAULTS: Dict[str, Any] = {
|
|
# A regex specifying the common denominator for all operation paths. If
|
|
# SCHEMA_PATH_PREFIX is set to None, drf-spectacular will attempt to estimate
|
|
# a common prefix. Use '' to disable.
|
|
# Mainly used for tag extraction, where paths like '/api/v1/albums' with
|
|
# a SCHEMA_PATH_PREFIX regex '/api/v[0-9]' would yield the tag 'albums'.
|
|
'SCHEMA_PATH_PREFIX': None,
|
|
# Remove matching SCHEMA_PATH_PREFIX from operation path. Usually used in
|
|
# conjunction with appended prefixes in SERVERS.
|
|
'SCHEMA_PATH_PREFIX_TRIM': False,
|
|
# Insert a manual path prefix to the operation path, e.g. '/service/backend'.
|
|
# Use this for example to align paths when the API is mounted as a sub-resource
|
|
# behind a proxy and Django is not aware of that. Alternatively, prefixes can
|
|
# also specified via SERVERS, but this makes the operation path more explicit.
|
|
'SCHEMA_PATH_PREFIX_INSERT': '',
|
|
# Coercion of {pk} to {id} is controlled by SCHEMA_COERCE_PATH_PK. Additionally,
|
|
# some libraries (e.g. drf-nested-routers) use "_pk" suffixed path variables.
|
|
# This setting globally coerces path variables like "{user_pk}" to "{user_id}".
|
|
'SCHEMA_COERCE_PATH_PK_SUFFIX': False,
|
|
|
|
# Schema generation parameters to influence how components are constructed.
|
|
# Some schema features might not translate well to your target.
|
|
# Demultiplexing/modifying components might help alleviate those issues.
|
|
'DEFAULT_GENERATOR_CLASS': 'drf_spectacular.generators.SchemaGenerator',
|
|
# Create separate components for PATCH endpoints (without required list)
|
|
'COMPONENT_SPLIT_PATCH': True,
|
|
# Split components into request and response parts where appropriate
|
|
# This setting is highly recommended to achieve the most accurate API
|
|
# description, however it comes at the cost of having more components.
|
|
'COMPONENT_SPLIT_REQUEST': False,
|
|
# Aid client generator targets that have trouble with read-only properties.
|
|
'COMPONENT_NO_READ_ONLY_REQUIRED': False,
|
|
|
|
# Adds "minLength: 1" to fields that do not allow blank strings. Deactivated
|
|
# by default because serializers do not strictly enforce this on responses and
|
|
# so "minLength: 1" may not always accurately describe API behavior.
|
|
# Gets implicitly enabled by COMPONENT_SPLIT_REQUEST, because this can be
|
|
# accurately modeled when request and response components are separated.
|
|
'ENFORCE_NON_BLANK_FIELDS': False,
|
|
|
|
# This version string will end up the in schema header. The default OpenAPI
|
|
# version is 3.0.3, which is heavily tested. We now also support 3.1.0,
|
|
# which contains the same features and a few mandatory, but minor changes.
|
|
'OAS_VERSION': '3.0.3',
|
|
|
|
# Configuration for serving a schema subset with SpectacularAPIView
|
|
'SERVE_URLCONF': None,
|
|
# complete public schema or a subset based on the requesting user
|
|
'SERVE_PUBLIC': True,
|
|
# include schema endpoint into schema
|
|
'SERVE_INCLUDE_SCHEMA': True,
|
|
# list of authentication/permission classes for spectacular's views.
|
|
'SERVE_PERMISSIONS': ['rest_framework.permissions.AllowAny'],
|
|
# None will default to DRF's AUTHENTICATION_CLASSES
|
|
'SERVE_AUTHENTICATION': None,
|
|
|
|
# Dictionary of general configuration to pass to the SwaggerUI({ ... })
|
|
# https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/
|
|
# The settings are serialized with json.dumps(). If you need customized JS, use a
|
|
# string instead. The string must then contain valid JS and is passed unchanged.
|
|
'SWAGGER_UI_SETTINGS': {
|
|
'deepLinking': True,
|
|
},
|
|
# Initialize SwaggerUI with additional OAuth2 configuration.
|
|
# https://swagger.io/docs/open-source-tools/swagger-ui/usage/oauth2/
|
|
'SWAGGER_UI_OAUTH2_CONFIG': {},
|
|
|
|
# Dictionary of general configuration to pass to the Redoc.init({ ... })
|
|
# https://redocly.com/docs/redoc/config/#functional-settings
|
|
# The settings are serialized with json.dumps(). If you need customized JS, use a
|
|
# string instead. The string must then contain valid JS and is passed unchanged.
|
|
'REDOC_UI_SETTINGS': {},
|
|
|
|
# CDNs for swagger and redoc. You can change the version or even host your
|
|
# own depending on your requirements. For self-hosting, have a look at
|
|
# the sidecar option in the README.
|
|
'SWAGGER_UI_DIST': 'https://cdn.jsdelivr.net/npm/swagger-ui-dist@latest',
|
|
'SWAGGER_UI_FAVICON_HREF': 'https://cdn.jsdelivr.net/npm/swagger-ui-dist@latest/favicon-32x32.png',
|
|
'REDOC_DIST': 'https://cdn.jsdelivr.net/npm/redoc@latest',
|
|
|
|
# Append OpenAPI objects to path and components in addition to the generated objects
|
|
'APPEND_PATHS': {},
|
|
'APPEND_COMPONENTS': {},
|
|
|
|
# STRONGLY DISCOURAGED (with the exception for the djangorestframework-api-key library)
|
|
# please don't use this anymore as it has tricky implications that
|
|
# are hard to get right. For authentication, OpenApiAuthenticationExtension are
|
|
# strongly preferred because they are more robust and easy to write.
|
|
# However if used, the list of methods is appended to every endpoint in the schema!
|
|
'SECURITY': [],
|
|
|
|
# Postprocessing functions that run at the end of schema generation.
|
|
# must satisfy interface result = hook(generator, request, public, result)
|
|
'POSTPROCESSING_HOOKS': [
|
|
'drf_spectacular.hooks.postprocess_schema_enums'
|
|
],
|
|
|
|
# Preprocessing functions that run before schema generation.
|
|
# must satisfy interface result = hook(endpoints=result) where result
|
|
# is a list of Tuples (path, path_regex, method, callback).
|
|
# Example: 'drf_spectacular.hooks.preprocess_exclude_path_format'
|
|
'PREPROCESSING_HOOKS': [],
|
|
|
|
# Determines how operations should be sorted. If you intend to do sorting with a
|
|
# PREPROCESSING_HOOKS, be sure to disable this setting. If configured, the sorting
|
|
# is applied after the PREPROCESSING_HOOKS. Accepts either
|
|
# True (drf-spectacular's alpha-sorter), False, or a callable for sort's key arg.
|
|
'SORT_OPERATIONS': True,
|
|
|
|
# enum name overrides. dict with keys "YourEnum" and their choice values "field.choices"
|
|
# e.g. {'SomeEnum': ['A', 'B'], 'OtherEnum': 'import.path.to.choices'}
|
|
'ENUM_NAME_OVERRIDES': {},
|
|
# Adds "blank" and "null" enum choices where appropriate. disable on client generation issues
|
|
'ENUM_ADD_EXPLICIT_BLANK_NULL_CHOICE': True,
|
|
# Add/Append a list of (``choice value`` - choice name) to the enum description string.
|
|
'ENUM_GENERATE_CHOICE_DESCRIPTION': True,
|
|
# Optional suffix for generated enum.
|
|
# e.g. {'ENUM_SUFFIX': "Type"} would produce an enum name 'StatusType'.
|
|
'ENUM_SUFFIX': 'Enum',
|
|
|
|
# function that returns a list of all classes that should be excluded from doc string extraction
|
|
'GET_LIB_DOC_EXCLUDES': 'drf_spectacular.plumbing.get_lib_doc_excludes',
|
|
|
|
# Function that returns a mocked request for view processing. For CLI usage
|
|
# original_request will be None.
|
|
# interface: request = build_mock_request(method, path, view, original_request, **kwargs)
|
|
'GET_MOCK_REQUEST': 'drf_spectacular.plumbing.build_mock_request',
|
|
|
|
# Camelize names like "operationId" and path parameter names
|
|
# Camelization of the operation schema itself requires the addition of
|
|
# 'drf_spectacular.contrib.djangorestframework_camel_case.camelize_serializer_fields'
|
|
# to POSTPROCESSING_HOOKS. Please note that the hook depends on
|
|
# ``djangorestframework_camel_case``, while CAMELIZE_NAMES itself does not.
|
|
'CAMELIZE_NAMES': False,
|
|
|
|
# Changes the location of the action/method on the generated OperationId. For example,
|
|
# "POST": "group_person_list", "group_person_create"
|
|
# "PRE": "list_group_person", "create_group_person"
|
|
'OPERATION_ID_METHOD_POSITION': 'POST',
|
|
|
|
# Determines if and how free-form 'additionalProperties' should be emitted in the schema. Some
|
|
# code generator targets are sensitive to this. None disables generic 'additionalProperties'.
|
|
# allowed values are 'dict', 'bool', None
|
|
'GENERIC_ADDITIONAL_PROPERTIES': 'dict',
|
|
|
|
# Path converter schema overrides (e.g. <int:foo>). Can be used to either modify default
|
|
# behavior or provide a schema for custom converters registered with register_converter(...).
|
|
# Takes converter labels as keys and either basic python types, OpenApiType, or raw schemas
|
|
# as values. Example: {'aint': OpenApiTypes.INT, 'bint': str, 'cint': {'type': ...}}
|
|
'PATH_CONVERTER_OVERRIDES': {},
|
|
|
|
# Determines whether operation parameters should be sorted alphanumerically or just in
|
|
# the order they arrived. Accepts either True, False, or a callable for sort's key arg.
|
|
'SORT_OPERATION_PARAMETERS': True,
|
|
|
|
# @extend_schema allows to specify status codes besides 200. This functionality is usually used
|
|
# to describe error responses, which rarely make use of list mechanics. Therefore, we suppress
|
|
# listing (pagination and filtering) on non-2XX status codes by default. Toggle this to enable
|
|
# list responses with ListSerializers/many=True irrespective of the status code.
|
|
'ENABLE_LIST_MECHANICS_ON_NON_2XX': False,
|
|
|
|
# This setting allows you to deviate from the default manager by accessing a different model
|
|
# property. We use "objects" by default for compatibility reasons. Using "_default_manager"
|
|
# will likely fix most issues, though you are free to choose any name.
|
|
"DEFAULT_QUERY_MANAGER": 'objects',
|
|
|
|
# Controls which authentication methods are exposed in the schema. If not None, will hide
|
|
# authentication classes that are not contained in the whitelist. Use full import paths
|
|
# like ['rest_framework.authentication.TokenAuthentication', ...].
|
|
# Empty list ([]) will hide all authentication methods. The default None will show all.
|
|
'AUTHENTICATION_WHITELIST': None,
|
|
# Controls which parsers are exposed in the schema. Works analog to AUTHENTICATION_WHITELIST.
|
|
# List of allowed parsers or None to allow all.
|
|
'PARSER_WHITELIST': None,
|
|
# Controls which renderers are exposed in the schema. Works analog to AUTHENTICATION_WHITELIST.
|
|
# rest_framework.renderers.BrowsableAPIRenderer is ignored by default if whitelist is None
|
|
'RENDERER_WHITELIST': None,
|
|
|
|
# Option for turning off error and warn messages
|
|
'DISABLE_ERRORS_AND_WARNINGS': False,
|
|
|
|
# Runs exemplary schema generation and emits warnings as part of "./manage.py check --deploy"
|
|
'ENABLE_DJANGO_DEPLOY_CHECK': True,
|
|
|
|
# General schema metadata. Refer to spec for valid inputs
|
|
# https://spec.openapis.org/oas/v3.0.3#openapi-object
|
|
'TITLE': '',
|
|
'DESCRIPTION': '',
|
|
'TOS': None,
|
|
# Optional: MAY contain "name", "url", "email"
|
|
'CONTACT': {},
|
|
# Optional: MUST contain "name", MAY contain URL
|
|
'LICENSE': {},
|
|
# Statically set schema version. May also be an empty string. When used together with
|
|
# view versioning, will become '0.0.0 (v2)' for 'v2' versioned requests.
|
|
# Set VERSION to None if only the request version should be rendered.
|
|
'VERSION': '0.0.0',
|
|
# Optional list of servers.
|
|
# Each entry MUST contain "url", MAY contain "description", "variables"
|
|
# e.g. [{'url': 'https://example.com/v1', 'description': 'Text'}, ...]
|
|
'SERVERS': [],
|
|
# Tags defined in the global scope
|
|
'TAGS': [],
|
|
# Optional: List of OpenAPI 3.1 webhooks. Each entry should be an import path to an
|
|
# OpenApiWebhook instance.
|
|
'WEBHOOKS': [],
|
|
# Optional: MUST contain 'url', may contain "description"
|
|
'EXTERNAL_DOCS': {},
|
|
|
|
# Arbitrary specification extensions attached to the schema's info object.
|
|
# https://swagger.io/specification/#specification-extensions
|
|
'EXTENSIONS_INFO': {},
|
|
|
|
# Arbitrary specification extensions attached to the schema's root object.
|
|
# https://swagger.io/specification/#specification-extensions
|
|
'EXTENSIONS_ROOT': {},
|
|
|
|
# Oauth2 related settings. used for example by django-oauth2-toolkit.
|
|
# https://spec.openapis.org/oas/v3.0.3#oauth-flows-object
|
|
'OAUTH2_FLOWS': [],
|
|
'OAUTH2_AUTHORIZATION_URL': None,
|
|
'OAUTH2_TOKEN_URL': None,
|
|
'OAUTH2_REFRESH_URL': None,
|
|
'OAUTH2_SCOPES': None,
|
|
}
|
|
|
|
IMPORT_STRINGS = [
|
|
'DEFAULT_GENERATOR_CLASS',
|
|
'SERVE_AUTHENTICATION',
|
|
'SERVE_PERMISSIONS',
|
|
'POSTPROCESSING_HOOKS',
|
|
'PREPROCESSING_HOOKS',
|
|
'GET_LIB_DOC_EXCLUDES',
|
|
'GET_MOCK_REQUEST',
|
|
'SORT_OPERATIONS',
|
|
'SORT_OPERATION_PARAMETERS',
|
|
'AUTHENTICATION_WHITELIST',
|
|
'RENDERER_WHITELIST',
|
|
'PARSER_WHITELIST',
|
|
'WEBHOOKS',
|
|
]
|
|
|
|
|
|
class SpectacularSettings(APISettings):
|
|
_original_settings: Dict[str, Any] = {}
|
|
|
|
def apply_patches(self, patches):
|
|
for attr, val in patches.items():
|
|
if attr.startswith('SERVE_') or attr == 'DEFAULT_GENERATOR_CLASS':
|
|
raise AttributeError(
|
|
f'{attr} not allowed in custom_settings. use dedicated parameter instead.'
|
|
)
|
|
if attr in self.import_strings:
|
|
val = perform_import(val, attr)
|
|
# load and store original value, then override __dict__ entry
|
|
self._original_settings[attr] = getattr(self, attr)
|
|
setattr(self, attr, val)
|
|
|
|
def clear_patches(self):
|
|
for attr, orig_val in self._original_settings.items():
|
|
setattr(self, attr, orig_val)
|
|
self._original_settings = {}
|
|
|
|
|
|
spectacular_settings = SpectacularSettings(
|
|
user_settings=getattr(settings, 'SPECTACULAR_SETTINGS', {}), # type: ignore
|
|
defaults=SPECTACULAR_DEFAULTS, # type: ignore
|
|
import_strings=IMPORT_STRINGS,
|
|
)
|
|
|
|
|
|
@contextmanager
|
|
def patched_settings(patches):
|
|
""" temporarily patch the global spectacular settings (or do nothing) """
|
|
if not patches:
|
|
yield
|
|
else:
|
|
try:
|
|
spectacular_settings.apply_patches(patches)
|
|
yield
|
|
finally:
|
|
spectacular_settings.clear_patches()
|