django-rest-framework icon indicating copy to clipboard operation
django-rest-framework copied to clipboard

StaticHTMLRenderer cannot handle ValidationError

Open sevdog opened this issue 1 year ago • 4 comments

Checklist

  • [ ] Raised initially as discussion #...
  • [x] This cannot be dealt with as a third party library. (We prefer new functionality to be in the form of third party libraries where possible.)
  • [x] I have reduced the issue to the simplest possible case.

Description

If any ValidationError is raised in a view which is going to use StaticHTMLRenderer then it will cause an error resulting in an Internal-Server-Error because the base class TemplateHTMLRenderer expectes to handle with a dict while in this case it receives a list instead.

https://github.com/encode/django-rest-framework/blob/0f39e0124d358b0098261f070175fa8e0359b739/rest_framework/renderers.py#L171-L175

Code sample

from django.test import TestCase
from rest_framework import exceptions
from rest_framework.renderers import StaticHTMLRenderer
from rest_framework.test import URLPatternsTestCase


class StaticHTMLRendererErrorTests(URLPatternsTestCase):
    class StaticErrorView(APIView):
        renderer_classes = (StaticHTMLRenderer,)

        def get(self, request, **kwargs):
            raise exceptions.ValidationError('error')

    urlpatterns = [path('error', StaticErrorView.as_view())]

    def test_statis_renderer_with_api_exception(self):
        response = self.client.get('/error')  # this line raise a TypeError
        assert response.status_code == 400

Stacktrace

TypeError: list indices must be integers or slices, not str
failed: tests/test_renderers.py:633: in test_statis_renderer_with_api_exception
    response = self.client.get('/error')
.venv/lib/python/site-packages/django/test/client.py:742: in get
    response = super().get(path, data=data, secure=secure, **extra)
.venv/lib/python/site-packages/django/test/client.py:398: in get
    **extra,
.venv/lib/python/site-packages/django/test/client.py:473: in generic
    return self.request(**r)
.venv/lib/python/site-packages/django/test/client.py:714: in request
    response = self.handler(environ)
.venv/lib/python/site-packages/django/test/client.py:145: in __call__
    response = self.get_response(request)
.venv/lib/python/site-packages/django/core/handlers/base.py:130: in get_response
    response = self._middleware_chain(request)
.venv/lib/python/site-packages/django/core/handlers/exception.py:49: in inner
    response = response_for_exception(request, exc)
.venv/lib/python/site-packages/django/core/handlers/exception.py:114: in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
.venv/lib/python/site-packages/django/core/handlers/exception.py:47: in inner
    response = get_response(request)
.venv/lib/python/site-packages/django/utils/deprecation.py:117: in __call__
    response = response or self.get_response(request)
.venv/lib/python/site-packages/django/core/handlers/exception.py:49: in inner
    response = response_for_exception(request, exc)
.venv/lib/python/site-packages/django/core/handlers/exception.py:114: in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
.venv/lib/python/site-packages/django/core/handlers/exception.py:47: in inner
    response = get_response(request)
.venv/lib/python/site-packages/django/utils/deprecation.py:117: in __call__
    response = response or self.get_response(request)
.venv/lib/python/site-packages/django/core/handlers/exception.py:49: in inner
    response = response_for_exception(request, exc)
.venv/lib/python/site-packages/django/core/handlers/exception.py:114: in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
.venv/lib/python/site-packages/django/core/handlers/exception.py:47: in inner
    response = get_response(request)
.venv/lib/python/site-packages/django/utils/deprecation.py:117: in __call__
    response = response or self.get_response(request)
.venv/lib/python/site-packages/django/core/handlers/exception.py:49: in inner
    response = response_for_exception(request, exc)
.venv/lib/python/site-packages/django/core/handlers/exception.py:114: in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
.venv/lib/python/site-packages/django/core/handlers/exception.py:47: in inner
    response = get_response(request)
.venv/lib/python/site-packages/django/utils/deprecation.py:117: in __call__
    response = response or self.get_response(request)
.venv/lib/python/site-packages/django/core/handlers/exception.py:49: in inner
    response = response_for_exception(request, exc)
.venv/lib/python/site-packages/django/core/handlers/exception.py:114: in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
.venv/lib/python/site-packages/django/core/handlers/exception.py:47: in inner
    response = get_response(request)
.venv/lib/python/site-packages/django/core/handlers/base.py:204: in _get_response
    response = response.render()
.venv/lib/python/site-packages/django/template/response.py:105: in render
    self.content = self.rendered_content
rest_framework/response.py:74: in rendered_content
    ret = renderer.render(self.data, accepted_media_type, context)
rest_framework/renderers.py:232: in render
    context = self.get_template_context(data, renderer_context)
rest_framework/renderers.py:174: in get_template_context
    data['status_code'] = response.status_code
E   TypeError: list indices must be integers or slices, not str

sevdog avatar Jan 04 '24 09:01 sevdog

Manage this branch in Squash

Test this branch here: https://lb-feature9771-move-wagtail-co-vsxst.squash.io

squash-labs[bot] avatar Oct 31 '23 21:10 squash-labs[bot]

I will look at the failing tests a bit later.

lb- avatar Oct 31 '23 22:10 lb-

Ok. Tests passing now.

lb- avatar Nov 01 '23 07:11 lb-

Adding to 6.1 milestone if that's OK @gasman & @thibaudcolas - this is a major un-blocker for CSP compliance.

I'll rebase this / update the upgrade considerations when the 6.1 release notes page is added.

lb- avatar Jan 30 '24 21:01 lb-