Separate documentations for internal and external APIs (drf_yasg) - django

I have two set of APIs: Internals, which are used in our client applications which we develop in our team, And externals, which is used by our business partners. I want to have a single document page which by authentication, shows internals APIs to our developers, and external APIs to every other viewer. How can I do that?
I use: Django, DRF, and drf-yasg.
P.S: I know this question is very general, but I do not have any clue where to start. I only guess some settings in get_schema_view, my views, and URL patterns are needed.

You can set the urlconf parameter in the get_schema_view(...) function
from django.urls import path
from rest_framework import permissions
from drf_yasg.views import get_schema_view
from drf_yasg import openapi
schema_view_internal = get_schema_view(
openapi.Info(
title="Snippets API",
default_version='v1',
description="Test description",
),
public=True,
permission_classes=(permissions.AllowAny,),
urlconf="path.to.your.internal_app.urls",
)
schema_view_public = get_schema_view(
openapi.Info(
title="Snippets API",
default_version='v1',
description="Test description",
),
public=True,
permission_classes=(permissions.AllowAny,),
urlconf="path.to.your.public_app.urls",
)
urlpatterns = [
path(
'public/swagger/',
schema_view_public.with_ui('swagger', cache_timeout=0),
name='schema-swagger-ui-internal'
),
path(
'internal/swagger/',
schema_view_internal.with_ui('swagger', cache_timeout=0),
name='schema-swagger-ui-internal'
),
]
Alternatively, you can set the patterns parameter also, which accept a list of URL patterns

Related

drf-yasg doesn't include the "api/" portion of the urls

I'm using drf-yasg to generate a Swagger schema, but it removes the "api/" portion of the url.
schema_view = get_schema_view(
openapi.Info(
title="My API",
default_version='v1',
description="...",
terms_of_service="https://www.google.com/policies/terms/",
contact=openapi.Contact(email="hello#mycompany.com"),
license=openapi.License(name="BSD License"),
),
public=True,
permission_classes=[permissions.AllowAny],
)
router = routers.DefaultRouter()
router.register(r'spaces', SpacesViewSet, basename='spaces')
urlpatterns = [
url(r'^swagger(?P<format>\.json|\.yaml)$', schema_view.without_ui(cache_timeout=0), name='schema-json'),
path('swagger/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
url(r'^redoc/$', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),
path('api/', include(router.urls)),
path('api/search-options', SearchPlacesOptionsView.as_view()),
]
result on /swagger
As you can see for the routes from the drf router, it doesn't include the /api portion of the url. However for the regular api/search-options endpoint it removes the /api portion as well, so I don't think it has something to do with the router.

Django - Disable authenticator for specific urls in urls.py?

So I have a Django app with Swagger, but I also added a custom authenticator to every endpoint automatically with
settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'cheers.utils.authenticator.CognitoAuthentication',
),
}
urls.py
schema_view = get_schema_view(
openapi.Info(
title="Resource API",
default_version="v1",
description="A sample API for resource with DRF",
terms_of_service="https://www.google.com/policies/terms/",
contact=openapi.Contact(email="cheersocialinc#gmail.com"),
license=openapi.License(name="BSD License"),
),
public=True,
permission_classes=(
permissions.AllowAny,), # Anyone have access to API documentation
)
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns += ADMIN_URLS
urlpatterns += SWAGGER_URLS
How do I turn this off for swagger and admin url? The reason I'm not sure is because Swagger and admin is added to URLs it's not a view
urls.py
How do I disable automatic authentication for swagger?
Also I guess a side question would be how to disable this URL when debug is False
To disable authentication | permission on swagger urls, set permission_classes in get_schema_view like this :
urls.py
from django.urls import path
from rest_framework import permissions
from rest_framework.schemas import get_schema_view
from django.conf import settings
schema_view = get_schema_view(
openapi.Info(
title="Resource API",
default_version="v1",
description="A sample API for resource with DRF",
terms_of_service="https://www.google.com/policies/terms/",
contact=openapi.Contact(email="your_email#yopmail.com"),
license=openapi.License(name="BSD License"),
),
public=True,
permission_classes=(
permissions.AllowAny, ), # Anyone have access to API documentation
)
if settings.DEBUG == False
# urlpatterns
urlpatterns = [
# Production urls only
]
else:
urlpatterns = [
# Production urls + swagger doc urls
path(
'doc/',
schema_view.with_ui('swagger', cache_timeout=0),
name='schema-swagger-ui'),
]
For Django admin without authentication follow this post.

Swagger Django [No operations defined in spec]

I have been trying to integrate Swagger with Django Application and encounter this error:
No operations defined in spec!
My project structure is
App
views.py
urls.py
..
App2
settings.py
urls.py
..
I am using drf_yasg for my purpose. I have included all details in settings.py and in App2 I have this in urls.py:
from rest_framework import permissions
from drf_yasg.views import get_schema_view
from drf_yasg import openapi
schema_view = get_schema_view(
openapi.Info(
title="Testing",
default_version='v1',
description="Doc Integration",
terms_of_service="https://www.google.com/policies/terms/",
contact=openapi.Contact(email="abc#abc.com"),
license=openapi.License(name="BSD License"),
),
public=True,
permission_classes=(permissions.AllowAny,),
)
urlpatterns=[path("admin/", admin.site.urls),
path("", include("app.urls")),
path('swagger/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
path('redoc', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),]
My class views such as (class Att(generic.TemplateView) and methods are declared in views.py under App. I tried methods such as #swagger_auto_schema, #api_view, to display app class and functions in the documentation. But it just returns No operations defined in spec!.
I tried using routers to register the view as well but did not work, even django-rest-swagger fails. Any help is appreciated. Thanks!
I have a project made of Django and I'm new to DRF. I had seen No operations defined in spec! as well while trying drf-yasg which is one of Swagger generators. Hope this way works for you.
I imported ->
from rest_framework.views import APIView
The class in views.py was like
class FeedView(View):
and the functions showed up when I changed the class like
class FeedView(APIView):
I need to deal with #swagger_auto_schema, #api_view to make my API document works with proper parameters.

How can i generate static api documentation for django rest APIs?

I went through the documentation and tried to use swagger and coreapi, but both are interactive, I want the same api documentation without interaction. Is it possible?
Here you can see API documentation
https://editor.swagger.io/
but its interacting with the respective api. I want same UI and without interaction.
Oh it is really easy.
First install: django-rest-swagger==2.1.2
Add to settings: 'rest_framework_swagger'
Next make urls.py changes:
from rest_framework_swagger.renderers import SwaggerUIRenderer, OpenAPIRenderer
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework import permissions
from rest_framework.renderers import CoreJSONRenderer
from rest_framework.schemas import get_schema_view
schema_view = get_schema_view(
title='Swagger My - API documentation',
public=True,
renderer_classes=[CoreJSONRenderer, OpenAPIRenderer, SwaggerUIRenderer],
authentication_classes=[JSONWebTokenAuthentication],
permission_classes=[permissions.AllowAny]
)
urlpatterns = [
# Swagger
path('docs/', schema_view),
]
And you choose renderer_classes=[CoreJSONRenderer, OpenAPIRenderer, SwaggerUIRenderer].
This is example with JWT JSONWebTokenAuthentication for auth.

drf-yasg provides wrong paths to URIs

In my application I need to have multiple Swagger pages with grouped endpoints for multiple clients.
One of my clients (paths) supplies mobile app API, another supplies web client API. URL patterns are kept in 2 different urls.py accordingly.
I'm using drf-yasg to generate schema for my API.
To generate swagger specification for those I'm initializing 2 separate schema_views for each urls.py file like this:
from api_mobile.urls import urlpatterns as mobile_patterns
from api_web.urls import urlpatterns as web_patterns
mobile_schema_view = get_schema_view(
openapi.Info(
title="Mobile API",
default_version='v3',
),
public=True,
permission_classes=(permissions.AllowAny,),
patterns=mobile_patterns,
)
web_schema_view = get_schema_view(
openapi.Info(
title="Web API",
default_version='v1',
),
public=True,
permission_classes=(permissions.AllowAny,),
patterns=web_patterns,
)
urlpatterns = [
path(
'api/mobile/docs',
mobile_schema_view.with_ui('swagger', cache_timeout=0),
name='mobile-schema-ui'
),
path(
'api/web/docs',
web_schema_view.with_ui('swagger', cache_timeout=0),
name='web-schema-ui'
),
path('api/mobile/v3/', include('api_mobile.urls'), name='mobile_urls'),
path('api/web/v1/', include('api_web.urls'), name='web_urls'),
...
]
Where mobile_patterns and web_patterns are just a list of url patterns.
If I open http://localhost:8000/api/mobile/docs or http://localhost:8000/api/web/docs I do see correctly generated schema for both lists of patterns, yet if I try to do a request directly from swagger specification page all endpoints return 404 error – they all try to do a request to non-existing url pattern without providing full path to endpoint.
So if I do a request to any view from mobile endpoints swagger tries to do a request at
http://localhost:8000/some_mobile_url/ instead of http://localhost:8000/api/mobile/v3/some_mobile_url/
And situation is the same for another schema, swagger wrongly requests http://localhost:8000/some_web_url/ instead of using full path
http://localhost:8000/api/web/v3/some_web_url/
Obviously being able to test API directly through swagger is very important so specification itself is not enough in my case.
Is this an issue in me misconfiguring swagger itlesf or should I be somehow providing path to swagger so it prepends full path to each url accordingly?
This is working fine for us:
api_schema.py
from django.conf.urls import include, url
from drf_yasg.views import get_schema_view
from drf_yasg import openapi
from books.api.v1.urls import urlpatterns as api_v1
API_DESCRIPTION = openapi.Info(
...
)
schema_view = get_schema_view(
info=...,
...
url='https://oursite.company.io/',
patterns=[
url('api/v1/', include(api_v1)),
],
)
books.api.v1.urls.py
from django.conf.urls import include, url
urlpatterns = [
url(r'^books', ...),
...
]
urls.py
from ...api_schema import schema_view
...
url(r'^api/v1/', include(api_v1)),
url(r'^api/schema(?P<format>\.json|\.yaml)$',
schema_view.without_ui(cache_timeout=0),
name='api_schema_v1'),
...