Repository: encode/django-rest-framework

Issue:
EXCEPTION_HANDLER on View.settings not respected
## Checklist

- [x] I have verified that that issue exists against the `master` branch of Django REST framework.
- [x] I have searched for similar issues in both open and closed tickets and cannot find a duplicate.
- [x] This is not a usage question. (Those should be directed to the [discussion group](https://groups.google.com/forum/#!forum/django-rest-framework) instead.)
- [x] This cannot be dealt with as a third party library. (We prefer new functionality to be [in the form of third party libraries](http://www.django-rest-framework.org/topics/third-party-resources/#about-third-party-packages) where possible.)
- [x] I have reduced the issue to the simplest possible case.
- [x] I have included a failing test as a pull request. (If you are unable to do so we can still accept the issue.)

## Steps to reproduce

1. Create a View with a custom `ApiSettings` with `EXCEPTION_HANDLER` specified
1. Trigger an exception and notice that the custom exception handler isn't triggered because the APIView class only ever uses `rest_framework.settings.api_settings`.

## Expected behavior

1. View uses `self.settings` since views can override settings objects so easily.

## Actual behavior

1. Uses default handler instead

## Extras

The 3.4 series used `self.settings.EXCEPTION_HANDLER` but 3.5 moved to use `get_exception_handler` which started using `rest_framework.settings.api_settings`.


Discussion:

Resolving patch:
diff --git a/rest_framework/views.py b/rest_framework/views.py
--- a/rest_framework/views.py
+++ b/rest_framework/views.py
@@ -290,7 +290,7 @@ def get_exception_handler(self):
         """
         Returns the exception handler that this view uses.
         """
-        return api_settings.EXCEPTION_HANDLER
+        return self.settings.EXCEPTION_HANDLER
 
     # API policy implementation methods
 


Test patch:
diff --git a/tests/test_views.py b/tests/test_views.py
--- a/tests/test_views.py
+++ b/tests/test_views.py
@@ -8,7 +8,7 @@
 from rest_framework import status
 from rest_framework.decorators import api_view
 from rest_framework.response import Response
-from rest_framework.settings import api_settings
+from rest_framework.settings import APISettings, api_settings
 from rest_framework.test import APIRequestFactory
 from rest_framework.views import APIView
 
@@ -45,6 +45,19 @@ def get(self, request, *args, **kwargs):
         raise Exception
 
 
+def custom_handler(exc, context):
+    if isinstance(exc, SyntaxError):
+        return Response({'error': 'SyntaxError'}, status=400)
+    return Response({'error': 'UnknownError'}, status=500)
+
+
+class OverridenSettingsView(APIView):
+    settings = APISettings({'EXCEPTION_HANDLER': custom_handler})
+
+    def get(self, request, *args, **kwargs):
+        raise SyntaxError('request is invalid syntax')
+
+
 @api_view(['GET'])
 def error_view(request):
     raise Exception
@@ -118,3 +131,14 @@ def test_function_based_view_exception_handler(self):
         expected = 'Error!'
         assert response.status_code == status.HTTP_400_BAD_REQUEST
         assert response.data == expected
+
+
+class TestCustomSettings(TestCase):
+    def setUp(self):
+        self.view = OverridenSettingsView.as_view()
+
+    def test_get_exception_handler(self):
+        request = factory.get('/', content_type='application/json')
+        response = self.view(request)
+        assert response.status_code == 400
+        assert response.data == {'error': 'SyntaxError'}