Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds a bit about redoc logo in docs, adds a custom_path_ordering hook, adds ability for configuring hooks from config #410

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/settings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -61,5 +61,13 @@ in your project files.
# available SwaggerUI versions: https://github.com/swagger-api/swagger-ui/releases
"SWAGGER_UI_DIST": "//unpkg.com/swagger-ui-dist@3.35.1", # default
"SWAGGER_UI_FAVICON_HREF": settings.STATIC_URL + "your_company_favicon.png", # default is swagger favicon

# example of adding a redoc logo
"EXTENSIONS_INFO": {
allen-munsch marked this conversation as resolved.
Show resolved Hide resolved
"x-logo": {
"url": "https://blahblah.cloudfront.net/static/img/logo-small.png",
"backgroundColor": "#FFFFFF",
"altText": "Nice Nice Logo"
}
...
}
14 changes: 11 additions & 3 deletions drf_spectacular/generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,15 @@ def get_schema(self, request=None, public=False):
components=self.registry.build(spectacular_settings.APPEND_COMPONENTS),
version=self.api_version or getattr(request, 'version', None),
)
for hook in spectacular_settings.POSTPROCESSING_HOOKS:
result = hook(result=result, generator=self, request=request, public=public)

try:
for hook, config in zip(
spectacular_settings.POSTPROCESSING_HOOKS,
spectacular_settings.POSTPROCESSING_HOOKS_CONFIGS
):
result = hook(result=result, generator=self, request=request, public=public, config=config)
except Exception:
# default
for hook in spectacular_settings.POSTPROCESSING_HOOKS:
result = hook(result=result, generator=self, request=request, public=public)
pass
return sanitize_result_object(normalize_result_object(result))
34 changes: 33 additions & 1 deletion drf_spectacular/hooks.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import re
from collections import defaultdict
from collections import OrderedDict, defaultdict

from inflection import camelize
from rest_framework.settings import api_settings
Expand All @@ -10,6 +10,38 @@
from drf_spectacular.settings import spectacular_settings


def custom_path_ordering(result, generator, **kwargs):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can see the need for custom endpoint order.

to me that looks like a perfect usage of PREPROCESSING_HOOKS: https://drf-spectacular.readthedocs.io/en/latest/customization.html#step-7-preprocessing-hooks

there you can filter and reorder the endpoints to your liking. Not sure if this adds anything substantial to that existing functionality?

"""
spectacular_settings.POSTPROCESSING_HOOKS_CONFIGS

use a list of strings for the config

The documentation will order based on the list, and then alphaetically for the rest
for example: ['schema', 'ping', 'hello']
would show in order 'schema', 'ping', 'hello', paths and then the rest
for duplicate endpoints you'll need to be more specific on which path is to be sorted
It looks at the full path when checking
['api/schema', 'api/ping', 'api/hello/read', ''api/hello/write']
"""
assert 'config' in kwargs, 'custom_path_ordering hook expected config in kwargs: ' + str(kwargs)
assert isinstance(kwargs['config'], list), 'custom_path_ordering hook expected a list of strings'
special_ordering = kwargs.get('config')
unordered = {}
the_rest = []
if 'paths' in result:
for key, value in result['paths'].items():
for x in special_ordering:
if x in key:
unordered.update({x: (key, value)})
break
else:
the_rest.append((key, value))
ordered = [unordered[x] for x in special_ordering]
result['paths'] = OrderedDict(ordered + the_rest)
return result
return result


def postprocess_schema_enums(result, generator, **kwargs):
"""
simple replacement of Enum/Choices that globally share the same name and have
Expand Down
14 changes: 13 additions & 1 deletion drf_spectacular/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,19 @@
# 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'
'drf_spectacular.hooks.postprocess_schema_enums',
# 'drf_spectacular.hooks.custom_path_ordering',
# 'your_module.hooks.something_special',

],
# must match the number of entries in POSTPROCESSING_HOOKS
# must satisfy interface result = hook(generator, request, public, result, config)
# where config matches what your hook is expecting
# zip(spectacular_settings.POSTPROCESSING_HOOKS, spectacular_settings.POSTPROCESSING_HOOKS_CONFIGS)
'POSTPROCESSING_HOOKS_CONFIGS': [
{}, # postprocess_schema_enums
# ['schema', 'ping'], # custom_path_ordering
# True, # something_special
],

# Preprocessing functions that run before schema generation.
Expand Down