diff --git a/arkindex/project/mixins.py b/arkindex/project/mixins.py index db62982097553bc2e262e1d7d8a9f2f2bbd91272..5a26c9de6548f7d56bc5f628ca2349a5bb81e958 100644 --- a/arkindex/project/mixins.py +++ b/arkindex/project/mixins.py @@ -1,6 +1,7 @@ from django.shortcuts import get_object_or_404 from django.conf import settings from django.core.exceptions import PermissionDenied +from django.views.decorators.cache import cache_page from rest_framework.exceptions import APIException, ValidationError from rest_framework.serializers import Serializer from arkindex.documents.models import Corpus, Right, Element @@ -144,3 +145,18 @@ class DeprecatedMixin(object): method = request.method.lower() if method in self.http_method_names and hasattr(self, method): raise DeprecatedAPIException(detail=getattr(self, 'deprecation_message', None)) + + +class CachedViewMixin(object): + """ + Add this mixin to any class-based view to cache it. + """ + cache_timeout = None + cache_prefix = None + + def __init__(self, *args, **kwargs): + if self.cache_timeout: + self.dispatch = cache_page( + self.cache_timeout, + key_prefix=self.cache_prefix, + )(self.dispatch) diff --git a/arkindex/project/urls.py b/arkindex/project/urls.py index 5ece3a876dccbdb1d5612a292b28cfe9f14f90bd..5e26e34ba4f10bc012687a633407a3ad3e447e0c 100644 --- a/arkindex/project/urls.py +++ b/arkindex/project/urls.py @@ -3,13 +3,14 @@ from django.conf import settings from django.contrib import admin from django.contrib.staticfiles.urls import staticfiles_urlpatterns from arkindex.project.api_v1 import api -from arkindex.project.views import FrontendView, CdnHome +from arkindex.project.views import FrontendView, CdnHome, OpenAPIDocsView # Fallback to the dummy frontend view when CDN_ASSETS_URL is not set frontend_view = FrontendView if settings.CDN_ASSETS_URL is None else CdnHome urlpatterns = [ path('api/v1/', include((api, 'api'), namespace='api')), + path('api-docs/', OpenAPIDocsView.as_view(), name='openapi-docs'), path('ponos/', include('ponos.urls')), path('admin/', admin.site.urls), # Frontend URLs the backend needs with django.urls.reverse diff --git a/arkindex/project/views.py b/arkindex/project/views.py index 80604c466df66deb275c2743a845b973110af258..ddb94f2a13ffef849741bd5f6db3fdb539ab1f4a 100644 --- a/arkindex/project/views.py +++ b/arkindex/project/views.py @@ -1,6 +1,7 @@ from django.views.generic import View, TemplateView -from django.views.decorators.cache import cache_page from django.conf import settings +from arkindex.project.mixins import CachedViewMixin +import arkindex class FrontendView(View): @@ -10,16 +11,13 @@ class FrontendView(View): """ -class CdnHome(TemplateView): +class CdnHome(CachedViewMixin, TemplateView): """ Index template to use frontend assets from a CDN """ template_name = 'index.html' - - def dispatch(self, *args, **kwargs): - # Cache rendered page - # On dev, by default a dummy cache is enabled - return cache_page(60 * 10)(super().dispatch)(*args, **kwargs) + cache_timeout = 86400 + cache_prefix = settings.FRONTEND_VERSION def get_context_data(self, *args, **kwargs): ctx = super().get_context_data(*args, **kwargs) @@ -30,3 +28,12 @@ class CdnHome(TemplateView): ctx['frontend_version'] = settings.FRONTEND_VERSION ctx['frontend_sentry_dsn'] = settings.FRONTEND_SENTRY_DSN return ctx + + +class OpenAPIDocsView(CachedViewMixin, TemplateView): + """ + OpenAPI documentation via ReDoc + """ + template_name = 'redoc.html' + cache_timeout = 86400 + cache_prefix = arkindex.VERSION diff --git a/arkindex/templates/redoc.html b/arkindex/templates/redoc.html new file mode 100644 index 0000000000000000000000000000000000000000..1501bfdb9ac2ba7bf7f4c34ca3cd84349973f27e --- /dev/null +++ b/arkindex/templates/redoc.html @@ -0,0 +1,23 @@ +{% load package_version %} +<!DOCTYPE html> +<html> + <head> + <title>Arkindex API {% package_version %}</title> + <!-- needed for adaptive design --> + <meta charset="utf-8"/> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet"> + <!-- ReDoc doesn't change outer page styles --> + <style> + body { + margin: 0; + padding: 0; + } + </style> + </head> + <body> + <!-- Add ?format=openapi to make ReDoc's download button get a YAML file, not HTML --> + <redoc spec-url="{% url 'api:openapi-schema' %}?format=openapi"></redoc> + <script src="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js"> </script> + </body> +</html>