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

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.

Related

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.

Django REST Framework API schema generation with same URL prefix

I'm documenting my Django application using get_schema_view() method, but when I open the Swagger UI all the URLs are placed under the same group.
My urls.py look like:
router = routers.DefaultRouter()
router.register(r'stores', StoreViewSet)
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include(router.urls)),
path('api/register/', UserRegistrationView.as_view(), name='register'),
path('api/login/', views.obtain_auth_token, name='login'),
# Documentation
path('openapi/', get_schema_view(
title='Title API',
description='Some description goes here...',
version='v0.1'
), name='openapi-schema'),
path('docs/', TemplateView.as_view(
template_name='documentation.html',
extra_context={'schema_url': 'openapi-schema'}
), name='docs')
]
All the endpoints are placed under a group called api in the Swagger UI.
How can I specify the api/ prefix while generating the schema in order to group the endpoints by model?
Thanks.
I had the same problem. The simple solution is to define prefix in settings.
SPECTACULAR_SETTINGS = {
'SCHEMA_PATH_PREFIX': r'/api/v[0-9]',
}
Answered here : Custom Grouping on OpenAPI endpoints with Django Rest Framework

How to configure Django VPS location in URL request

I am trying to configure my Django app (Djnago 3.05) to work from a server location.
The location is http://dev.apps.net/tac.
How do i include this in each request?
I managed to do this if adding in views.py the '/tac' prefix and add a folder named 'tac' in which all the templates exist.
myviews.py
#login_required
def item_list(request):
meta = "V1.1"
if not any(field in request.GET for field in set(UserFilter.get_fields())):
user_list = item.objects.order_by("-date").all()[:50]
else:
user_list = item.objects.order_by("-date").all()
user_filter = UserFilter(request.GET, queryset=user_list)
return render(request, "tac/items/item_list.html", {"filter": user_filter})
urls.py
urlpatterns = [
url(
r"^login/$",
admin_views.LoginView.as_view(template_name="registration/login.html"),
name="login",
),
url(r"^$", TemplateView.as_view(template_name="home.html"), name="home"),
url(r"^input/$", views.inputprocess, name="inputprocess"),
url(r"^items/$", views.item_list, name="item_list"),
url(r"^items/create/$", views.item_create, name="item_create"),
url(r"^items/(?P<pk>\d+)/update/$", views.item_update, name="item_update"),
url(r"^items/(?P<pk>\d+)/delete/$", views.item_delete, name="item_delete"),
url(r"^reports/$", views.reports, name="reports"),
url(r"^timeline/$", views.timeline, name="timeline"),
url(r"^support/$", views.support, name="support"),
url(r"^dbToools/$", views.dbTools, name="dbTools"),
url(r"^logout/$", views.logout_view, name="logout_view"),
url(r"^upload/$", views.upload, name="upload"),
path("accounts/login/", auth_views.LoginView.as_view()),
path("admin/", admin.site.urls),
]
I am not sure if this is the correct way. How could I do this more efficient? Could you guys please help me here?
Thanks!
I managed to solve this using this config for urls.py (i found it in another post here)
urlpatterns = [
url(
r"^tac/",
include(
[
url(
r"^login/$",
admin_views.LoginView.as_view(
template_name="registration/login.html"
),
name="login",
),
url(
r"^$", TemplateView.as_view(template_name="home.html"), name="home"
),
url(r"^input/$", views.inputprocess, name="inputprocess"),
url(r"^items/$", views.item_list, name="item_list"),
url(r"^items/create/$", views.item_create, name="item_create"),
url(
r"^items/(?P<pk>\d+)/update/$",
views.item_update,
name="item_update",
),
url(
r"^items/(?P<pk>\d+)/delete/$",
views.item_delete,
name="item_delete",
),
url(r"^reports/$", views.reports, name="reports"),
url(r"^timeline/$", views.timeline, name="timeline"),
url(r"^support/$", views.support, name="support"),
url(r"^dbToools/$", views.dbTools, name="dbTools"),
url(r"^logout/$", views.logout_view, name="logout_view"),
url(r"^upload/$", views.upload, name="upload"),
path("accounts/login/", auth_views.LoginView.as_view()),
path("admin/", admin.site.urls),
]
),
),
]

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'),
...

Remove user endpoints in Django rest auth

I am using Django rest auth for user account handling. For updating user info i have created custom endpoints, So i don't need the djnago-rest-auth generated endpoints /rest-auth/user/ (GET, PUT, PATCH). How can i remove these endpoints?
urls.py
urlpatterns = [
path('', include("rest_auth.urls"), name="user-auth"),
path('register', include('rest_auth.registration.urls'), name="user-auth-registration"),
path('<uid>/', views.UserProfileView.as_view(), name="user-profile"),
]
Edit
I want to use all other urls of rest-auth like login, register, etc. But i just dont want the /rest-auth/user/ as described here.
#bodoubleu 's answer didn't work, So i added them manually.
from rest_auth.views import (
LoginView, LogoutView, PasswordChangeView,
PasswordResetView, PasswordResetConfirmView
)
urlpatterns = [
path('register', include('rest_auth.registration.urls'), name="user-auth-registration"),
path('login', LoginView.as_view(), name="user-login"),
path('logout', LogoutView.as_view(), name='user-logout'),
path('password/change/', PasswordChangeView.as_view(), name='rest_password_change'),
path('password/reset', PasswordResetView.as_view(), name='rest_password_reset'),
path('password/reset/confirm/', PasswordResetConfirmView.as_view(), name='rest_password_reset_confirm'),
path('<uid>/', views.UserProfileView.as_view(), name="user-profile"),
]
Untested but this should work.
urlpatterns = [
path('user/', django.views.defaults.page_not_found),
path('', include("rest_auth.urls"), name="user-auth"),
path('register', include('rest_auth.registration.urls'), name="user-auth-registration"),
path('<uid>/', views.UserProfileView.as_view(), name="user-profile"),
]
If not you can manually define all the rest_auth.urls in your url patterns