master branch of Django REST framework.DRF >= 3.7.4 and Django 2
Try a basic view similar to this.
class FooList(generics.ListAPIView):
permission_classes = (permissions.isAuthenticated,)
model = Foo
serializer_class = FooSerializer
pagination_class = None
def get_queryset(self):
return Foo.objects.filter(business_logic_here)
More discussion here: https://groups.google.com/d/msg/django-rest-framework/mxzgI0n_VZg/ra-M95fhCgAJ
Valid Http response
Works fine in 3.7.3, fails in >= 3.7.4. Traceback: (assuming our venv is in /srv)
File “/srv/lib/python3.6/site-packages/django/core/handlers/exception.py” in inner
35. response = get_response(request)
File “/srv/lib/python3.6/site-packages/django/core/handlers/base.py” in _get_response
128. response = self.process_exception_by_middleware(e, request)
File “/srv/lib/python3.6/site-packages/django/core/handlers/base.py” in _get_response
126. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File “/srv/lib/python3.6/site-packages/django/views/decorators/csrf.py” in wrapped_view
54. return view_func(*args, **kwargs)
File “/srv/lib/python3.6/site-packages/django/views/generic/base.py” in view
69. return self.dispatch(request, *args, **kwargs)
File “/srv/lib/python3.6/site-packages/django/utils/decorators.py” in _wrapper
62. return bound_func(*args, **kwargs)
File “/srv/lib/python3.6/site-packages/django/views/decorators/csrf.py” in wrapped_view
54. return view_func(*args, **kwargs)
File “/srv/lib/python3.6/site-packages/django/views/generic/base.py” in view
69. return self.dispatch(request, *args, **kwargs)
File “/srv/lib/python3.6/site-packages/rest_framework/views.py” in dispatch
494. response = self.handle_exception(exc)
File “/srv/lib/python3.6/site-packages/rest_framework/views.py” in handle_exception
454. self.raise_uncaught_exception(exc)
File “/srv/lib/python3.6/site-packages/rest_framework/views.py” in dispatch
491. response = handler(request, *args, **kwargs)
File “/srv/lib/python3.6/site-packages/rest_framework/decorators.py” in handler
53. return func(*args, **kwargs)
File “/srv/lib/python3.6/site-packages/django/utils/decorators.py” in bound_func
58. return func.__get__(self, type(self))(*args2, **kwargs2)
File “/srv/lib/python3.6/site-packages/rest_framework/views.py” in dispatch
477. request = self.initialize_request(request, *args, **kwargs)
File “/srv/lib/python3.6/site-packages/rest_framework/views.py” in initialize_request
381. parser_context=parser_context
File “/srv/lib/python3.6/site-packages/rest_framework/request.py” in _init_
159. .format(request.__class__.__module__, request.__class__.__name__)
Exception Type: AssertionError at /API/foo/the_pk/ Exception Value: The `request` argument must be an instance of `django.http.HttpRequest`, not `rest_framework.request.Request`.
This part of the trace doesn't looks right:
File “/srv/lib/python3.6/site-packages/rest_framework/views.py” in dispatch
494. response = self.handle_exception(exc)
File “/srv/lib/python3.6/site-packages/rest_framework/views.py” in handle_exception
454. self.raise_uncaught_exception(exc)
File “/srv/lib/python3.6/site-packages/rest_framework/views.py” in dispatch
491. response = handler(request, *args, **kwargs)
File “/srv/lib/python3.6/site-packages/rest_framework/decorators.py” in handler
53. return func(*args, **kwargs)
handle_exception doesn't re-dispatch a view.
Can you provide more context? Or, better yet, add a test case which demonstrates this behaviour.
(As described this is a pretty basic use-case, which is covered by the test suite, so it looks like something else is going on in your project.)
Let's close this off. We can consider re-opening if there's more info or if anyone else confirms similar issue.
I seem to be suffering from this same issue. I'm trying to return the response from a different view function from my view. i.e. I'm calling another view function and passing in the request I got passed. e.g. return my_other_view(request, slug)
I've worked around it by changing the above to my_other_view(request._request, slug), which seems a little hacky.
Hi @lllama. There is related discussion in #5771, but the short answer is that requests are not designed to be reprocessed by a view, and there may be unintended side effects. You can do this safely under certain conditions, but it's not supported functionality. i.e., it is hacky.
Thanks @rpkilby I've looked through our code path and it looks like we were being super lazy and perhaps taking DRY a little too far. I'll copy/paste the ~5 lines of code and remove the hack.
What are the ~5 lines of code we can use instead of the _request hack? @lllama
@littlehome-eugene: Extract your business logic into a reusable function, so it can be imported and called independently of the request-reponse cycle. Then call that in your other view, rather than reusing the view directly. (That's it. 🙂)
Most helpful comment
I seem to be suffering from this same issue. I'm trying to return the response from a different view function from my view. i.e. I'm calling another view function and passing in the request I got passed. e.g.
return my_other_view(request, slug)I've worked around it by changing the above to
my_other_view(request._request, slug), which seems a little hacky.