Reputation: 1881
I have a Django project and I am using Django REST framework. I am using drf-spectacular for OpenAPI representation, but I think my problem is not tied to this package, it's seems a more generic OpenAPI thing to me (but not 100% sure if I am right to this).
Assume that I have a URL structure like this:
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include([
path('v1/', include([
path('auth/', include('rest_framework.urls', namespace='rest_framework')),
path('jwt-auth/token/obtain', CustomTokenObtainPairView.as_view(), name='token_obtain_pair'),
path('jwt-auth/token/refresh', CustomTokenRefreshView.as_view(), name='token_refresh'),
path('home/', include("home.urls"))
]))
])),
# OpenAPI endpoints
path('swagger/', SpectacularSwaggerView.as_view(url_name='schema-swagger-json'), name='schema-swagger-ui'),
path('swagger.yaml/', SpectacularAPIView.as_view(), name='schema-swagger-yaml'),
path('swagger.json/', SpectacularJSONAPIView.as_view(), name='schema-swagger-json'),
path('redoc/', SpectacularRedocView.as_view(url_name='schema-swagger-yaml'), name='schema-redoc'),
]
In the corresponding swagger UI view, I get all endpoints grouped under api endpoint, e.g.:
If add more endpoints under v1, all go under the api endpoint.
What I want to achieve is, to have the endpoints in Swagger grouped differently, e.g. by app. So I'd have home, jwt, another_endpoint, instead of just api, so it will be easier to navigate in Swagger (when I add more endpoints, with the current method it's just showing a massive list of URLs, not very user friendly).
I've read that those groups are being extracted from the first path of a URL, in my case this is api, so if I change the URL structure, I could achieve what I need.
But isn't there another way of doing this? I want to keep my URL structure, and customize how I display this with OpenAPI, so in the end I have a swagger that groups the endpoints by app, so it's easier to navigate and find what you are looking for.
Upvotes: 15
Views: 10208
Reputation: 21
just use this decorator above your view to group your end points:
@extend_schema(
description='Store end point',
tags=['Stores']
)
class Store(viewsets.ModelViewSet):
... rest of your code
Upvotes: 2
Reputation: 1881
Turns out that you can control this by changing the tags in a view, as per OpenAPI specification: https://swagger.io/docs/specification/grouping-operations-with-tags/
So, with drf-spectacular, you can use the extend_schema decorator to achieve this, e.g.:
from drf_spectacular.utils import extend_schema
class CustomTokenObtainPairView(TokenObtainPairView):
"""
Takes a set of user credentials and returns an access and refresh JSON web
token pair to prove the authentication of those credentials.
"""
@extend_schema(
operation_id="jwt_obtain",
....
tags=["aTestTag"]
)
def post(self, request, *args, **kwargs):
# whatever
So you have to use this decorator to extend the schema in each view that you want to put into a custom group.
Upvotes: 13
Reputation: 1871
you are making it harder than it needs to be. In the global settings you can specify a common prefix regex that strips the unwanted parts. that would clean up both operation_id
and tags
for you. In your case that would probably be:
SPECTACULAR_SETTINGS = {
'SCHEMA_PATH_PREFIX': r'/api/v[0-9]',
}
that should result in tags: home, jwt-auth, swagger.json, swagger.yaml
the tags
on @extend_schema
is merely a convenience to deviate from the default where needed. it would be cumbersome to do this for every operation. see the settings for more details:
https://drf-spectacular.readthedocs.io/en/latest/settings.html
for even more elaborate tagging you can always subclass AutoSchema
and override get_tags(self)
to your liking. cheers!
Upvotes: 35