diff --git a/CHANGELOG.md b/CHANGELOG.md index 7810af39..ad1ecbe6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,11 @@ any parts of the framework not mentioned in the documentation should generally b * Removed support for Django REST Framework <=3.8. * Removed support for Django 2.0. +### Fixed + +* Avoid printing invalid pointer when api returns 404 + + ## [2.8.0] - 2019-06-13 This is the last release supporting Python 2.7, Python 3.4, Django Filter 1.1, Django REST Framework <=3.8 and Django 2.0. diff --git a/example/tests/test_model_viewsets.py b/example/tests/test_model_viewsets.py index 185ebcdc..1fe191c1 100644 --- a/example/tests/test_model_viewsets.py +++ b/example/tests/test_model_viewsets.py @@ -212,6 +212,19 @@ def test_key_in_post(self): get_user_model().objects.get(pk=self.miles.pk).email, 'miles@trumpet.org') + def test_404_error_pointer(self): + self.client.login(username='miles', password='pw') + not_found_url = reverse('user-detail', kwargs={'pk': 12345}) + errors = { + 'errors': [ + {'detail': 'Not found.', 'status': '404'} + ] + } + + response = self.client.get(not_found_url) + assert 404 == response.status_code + assert errors == response.json() + @pytest.mark.django_db def test_patch_allow_field_type(author, author_type_factory, client): diff --git a/rest_framework_json_api/utils.py b/rest_framework_json_api/utils.py index 600bf358..ff299772 100644 --- a/rest_framework_json_api/utils.py +++ b/rest_framework_json_api/utils.py @@ -11,6 +11,7 @@ ManyToManyDescriptor, ReverseManyToOneDescriptor ) +from django.http import Http404 from django.utils import encoding from django.utils.module_loading import import_string as import_class_from_dotted_path from django.utils.translation import ugettext_lazy as _ @@ -405,6 +406,12 @@ def format_drf_errors(response, context, exc): # see if they passed a dictionary to ValidationError manually if isinstance(error, dict): errors.append(error) + elif isinstance(exc, Http404) and isinstance(error, str): + # 404 errors don't have a pointer + errors.append({ + 'detail': error, + 'status': encoding.force_text(response.status_code), + }) elif isinstance(error, str): classes = inspect.getmembers(exceptions, inspect.isclass) # DRF sets the `field` to 'detail' for its own exceptions