I have configured Wagtail API
as prescribed in the docs and it works nicely when using curl
:
$ curl -LsD- http://127.0.0.1:8080/rest/p/
HTTP/1.1 200 OK
Date: Fri, 22 May 2020 17:33:58 GMT
Server: WSGIServer/0.2 CPython/3.8.2
Content-Type: application/json
Vary: Accept, Cookie
Allow: GET, HEAD, OPTIONS
X-Frame-Options: DENY
Content-Length: 433
X-Content-Type-Options: nosniff
{
"meta": {
"total_count": 1
},
"items": [
{
"id": 2,
"meta": {
"type": "wagtailcore.Page",
"detail_url": "http://localhost/rest/p/2/",
"html_url": "http://localhost/",
"slug": "home",
"first_published_at": null
},
"title": "Welcome to your new Wagtail site!"
}
]
}
Wagtail doc state the following:
Optionally, you may also want to add rest_framework to INSTALLED_APPS. This would make the API browsable when viewed from a web browser but is not required for basic JSON-formatted output.
This is kind of true, because API works fine via curl
, however if I do not add rest_framework
to the INSTALLED_APPS
and then try to access the same url via browser I do get http 500
, namely because application throws an exception:
Internal Server Error: /rest/p/
Traceback (most recent call last):
File "/usr/local/lib/python3.8/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/usr/local/lib/python3.8/site-packages/django/core/handlers/base.py", line 145, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/usr/local/lib/python3.8/site-packages/django/core/handlers/base.py", line 143, in _get_response
response = response.render()
File "/usr/local/lib/python3.8/site-packages/django/template/response.py", line 105, in render
self.content = self.rendered_content
File "/usr/local/lib/python3.8/site-packages/rest_framework/response.py", line 70, in rendered_content
ret = renderer.render(self.data, accepted_media_type, context)
File "/usr/local/lib/python3.8/site-packages/rest_framework/renderers.py", line 723, in render
template = loader.get_template(self.template)
File "/usr/local/lib/python3.8/site-packages/django/template/loader.py", line 19, in get_template
raise TemplateDoesNotExist(template_name, chain=chain)
django.template.exceptions.TemplateDoesNotExist: rest_framework/api.html
So it seems to me that if I don't want to jam my email with django
exceptions, then rest_framework
is a mandatory app in my prod site settings? Did I miss some configuration detail? What is the best way to address this issue?
I don't want that my live site would be throwing 500 all the time and also I don't strictly need this nice and shining api interface.
Added relevant rest_framework
config:
REST_FRAMEWORK = {
"DEFAULT_PERMISSION_CLASSES": [
"rest_framework.permissions.IsAuthenticatedOrReadOnly",
],
"DEFAULT_RENDERER_CLASSES": [
"rest_framework.renderers.JSONRenderer",
],
}
By looking to the debug tracebacks it seems that Wagtail
is somehow enforcing rest_framework.renderers.BrowsableAPIRenderer
renderer, even though REST_FRAMEWORK
is not configured to use it?
Apparently Wagtail
indeed ignores REST_FRAMEWORK
settings and instead uses hardcoded renderer_classes which are [JSONRenderer, BrowsableAPIRenderer]
.
Potentially it's a bug in a Wagtail
as it ignores REST_FRAMEWORK
configuration in the settings and instead uses hardcoded renderer_classes which currently are [JSONRenderer, BrowsableAPIRenderer]
.
To overcome this issue one may set up Wagtail API
like the following:
from django.conf import settings
from wagtail.api.v2.views import PagesAPIViewSet
from wagtail.api.v2.router import WagtailAPIRouter
if not settings.DEBUG:
from rest_framework.renderers import JSONRenderer
class ProdPagesAPIViewSet(PagesAPIViewSet):
renderer_classes = [JSONRenderer]
PagesAPIViewSet = ProdPagesAPIViewSet
api_router = WagtailAPIRouter("wagtailapi")
api_router.register_endpoint("p", PagesAPIViewSet)