Skip to content

Commit 67e56af

Browse files
authored
Replace deprecated coreapi with drf-yasg for API documentation (#314)
Signed-off-by: tdruez <[email protected]>
1 parent 14eb7e8 commit 67e56af

21 files changed

+40
-219
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ postgresdb_clean:
136136
@${SUDO_POSTGRES} dropuser '${DB_USERNAME}' || true
137137

138138
run:
139-
${MANAGE} runserver 8000 --insecure
139+
DJANGO_RUNSERVER_HIDE_WARNING=true ${MANAGE} runserver 8000 --insecure
140140

141141
worker:
142142
${MANAGE} rqworker

component_catalog/api.py

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,13 @@
1111
from django.db import transaction
1212
from django.forms.widgets import HiddenInput
1313

14-
import coreapi
15-
import coreschema
1614
import django_filters
1715
from packageurl.contrib import url2purl
1816
from packageurl.contrib.django.filters import PackageURLFilter
1917
from rest_framework import serializers
2018
from rest_framework.decorators import action
2119
from rest_framework.fields import ListField
2220
from rest_framework.response import Response
23-
from rest_framework.schemas import AutoSchema
2421

2522
from component_catalog.admin import ComponentAdmin
2623
from component_catalog.admin import PackageAdmin
@@ -922,24 +919,7 @@ def about(self, request, uuid):
922919
package = self.get_object()
923920
return Response({"about_data": package.as_about_yaml()})
924921

925-
download_url_description = (
926-
"A single, or list of, Download URL(s).<br><br>"
927-
'<b>cURL style</b>: <code>-d "download_url=url1&download_url=url2"</code><br><br>'
928-
'<b>Python</b>: <code>data = {"download_url": ["url1", "url2"]}</code>'
929-
)
930-
931-
add_action_schema = AutoSchema(
932-
manual_fields=[
933-
coreapi.Field(
934-
"download_url",
935-
required=True,
936-
location="body",
937-
schema=coreschema.String(description=download_url_description),
938-
),
939-
]
940-
)
941-
942-
@action(detail=False, methods=["post"], name="Package Add", schema=add_action_schema)
922+
@action(detail=False, methods=["post"], name="Package Add")
943923
def add(self, request):
944924
"""
945925
Alternative way to add a package providing only its `download_url`.

dejacode/settings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ def gettext_noop(s):
317317
"django.contrib.admin",
318318
"rest_framework",
319319
"rest_framework.authtoken",
320+
"drf_yasg",
320321
"django_rq",
321322
"crispy_forms",
322323
"crispy_bootstrap5",
@@ -625,7 +626,6 @@ def get_fake_redis_connection(config, use_strict_redis):
625626
"user": REST_API_RATE_THROTTLE,
626627
},
627628
"DEFAULT_PAGINATION_CLASS": "dje.api_custom.PageSizePagination",
628-
"DEFAULT_SCHEMA_CLASS": "rest_framework.schemas.coreapi.AutoSchema",
629629
"VIEW_NAME_FUNCTION": "dje.api_custom.get_view_name",
630630
"URL_FIELD_NAME": "api_url", # Default 'url' used as a field on the Package model
631631
}

dejacode/urls.py

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,12 @@
1111
from django.contrib import admin
1212
from django.contrib.auth import views as auth_views
1313
from django.contrib.auth.decorators import login_required
14-
from django.template.loader import render_to_string
1514
from django.urls import path
1615
from django.views.defaults import page_not_found
1716
from django.views.generic import RedirectView
1817
from django.views.generic import TemplateView
1918

2019
from notifications.views import mark_all_as_read
21-
from rest_framework.documentation import include_docs_urls
2220
from rest_framework.routers import DefaultRouter
2321

2422
from component_catalog.api import ComponentViewSet
@@ -39,6 +37,7 @@
3937
from dje.views import GlobalSearchListView
4038
from dje.views import IntegrationsStatusView
4139
from dje.views import UnreadNotificationsList
40+
from dje.views import api_docs_view
4241
from dje.views import home_view
4342
from dje.views import index_dispatch
4443
from dje.views import urn_resolve_view
@@ -161,28 +160,16 @@
161160

162161
urlpatterns += [
163162
path("notifications/", include((notification_patterns, "notifications"))),
164-
]
165-
166-
urlpatterns += [
167163
path("purldb/", include(("purldb.urls", "purldb"))),
168164
]
169165

170-
api_docs_urls = include_docs_urls(
171-
title="DejaCode REST API",
172-
public=False,
173-
description=render_to_string(
174-
"rest_framework/docs/description.html",
175-
context={"site_url": settings.SITE_URL.rstrip("/")},
176-
),
177-
)
178-
179-
# Force login_required on all API documentation URLs.
180-
for doc_url in api_docs_urls[0]:
181-
doc_url.callback = login_required(doc_url.callback)
166+
api_docs_patterns = [
167+
path("", login_required(api_docs_view.with_ui("redoc")), name="docs-index"),
168+
]
182169

183170
urlpatterns += [
184171
path("api/v2/", include((api_router.urls, "api_v2"))),
185-
path("api/v2/docs/", api_docs_urls),
172+
path("api/v2/docs/", include((api_docs_patterns, "api-docs"))),
186173
]
187174

188175
if settings.ENABLE_SELF_REGISTRATION:

dje/templates/admin/docs/index.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919

2020
{% if code_style %}<style>{{ code_style }}</style>{% endif %}
2121
<script src="{% static 'rest_framework/js/coreapi-0.1.1.js' %}"></script>
22-
<script src="{% url 'api-docs:schema-js' %}"></script>
2322

2423
<script src="{% static 'rest_framework/js/jquery-3.7.1.min.js' %}"></script>
2524
<script src="{% static 'rest_framework/js/bootstrap.min.js' %}"></script>

dje/templates/rest_framework/docs/index.html

Lines changed: 0 additions & 85 deletions
This file was deleted.

dje/tests/test_admin.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,16 @@ def test_admin_history_view_content(self):
6565
self.assertContains(response, "<td>Added.</td>")
6666
self.assertContains(response, "<td>Changed name.</td>")
6767

68+
def test_admin_docs_models_view(self):
69+
url_docs_models = reverse("admin:docs_models")
70+
response = self.client.get(url_docs_models)
71+
self.assertEqual(302, response.status_code)
72+
self.assertRedirects(response, f"/login/?next={url_docs_models}")
73+
74+
self.client.login(username=self.super_user.username, password="secret")
75+
response = self.client.get(url_docs_models)
76+
self.assertContains(response, "Models documentation")
77+
6878
def test_dataspaced_admin_advanced_search_method(self):
6979
search_fields = ["f1", "f2"]
7080

dje/views.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
from django.shortcuts import redirect
5050
from django.shortcuts import render
5151
from django.template.defaultfilters import pluralize
52+
from django.template.loader import render_to_string
5253
from django.test import RequestFactory
5354
from django.urls import NoReverseMatch
5455
from django.urls import reverse
@@ -70,6 +71,8 @@
7071

7172
import django_otp
7273
from django_filters.views import FilterView
74+
from drf_yasg import openapi
75+
from drf_yasg.views import get_schema_view
7376
from grappelli.views.related import AutocompleteLookup
7477
from grappelli.views.related import RelatedLookup
7578
from notifications import views as notifications_views
@@ -2429,3 +2432,16 @@ def get(self, request, *args, **kwargs):
24292432
filename=filename,
24302433
content_type="application/json",
24312434
)
2435+
2436+
2437+
api_docs_view = get_schema_view(
2438+
openapi.Info(
2439+
title="DejaCode REST API",
2440+
default_version="v2",
2441+
description=render_to_string(
2442+
"rest_framework/docs/description.html",
2443+
context={"site_url": settings.SITE_URL.rstrip("/")},
2444+
),
2445+
),
2446+
public=False,
2447+
)

setup.cfg

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,11 @@ install_requires =
7070
django_altcha==0.1.3
7171
# REST API
7272
djangorestframework==3.16.0
73-
# API documentation, `coreapi` and its requirements:
74-
coreapi==2.3.3
75-
MarkupSafe==3.0.2
76-
coreschema==0.0.4
77-
itypes==1.2.0
78-
Jinja2==3.1.6
73+
# API documentation
74+
drf-yasg==1.21.10
7975
uritemplate==4.1.1
76+
inflection==0.5.1
77+
pytz==2025.2
8078
# Track failed login attempts
8179
django-axes==8.0.0
8280
# Multi-factor authentication
@@ -150,6 +148,8 @@ install_requires =
150148
# AboutCode Toolkit
151149
aboutcode_toolkit==11.1.1
152150
click==8.2.1
151+
Jinja2==3.1.6
152+
MarkupSafe==3.0.2
153153
saneyaml==0.6.1
154154
openpyxl==3.1.5
155155
et-xmlfile==2.0.0
-25 KB
Binary file not shown.

0 commit comments

Comments
 (0)