Repository: encode/django-rest-framework

Issue:
initialize_request in view.py converts the request in Request without checking the incoming request type
I am trying to call a class baed view from another class based view using [This SO](http://stackoverflow.com/questions/14956678/django-call-class-based-view-from-another-class-based-view) post. I called a class baed view by passing in the request like `MyClassBasedView.as_view()(request)`. When I tried to access the HTTPRequest from request, I had to access it like request._request._request, instead of request._request. I checked the code in views.py and it is converting the incoming request to Request without checking the instance of request. I managed it by using `MyClassBasedView.as_view()(request._request)`
This is my first reporting of an issue. Please be gentle if I violated any guideline. 



Discussion:
Calling a view from another view isn't really supported behavior so odd things may happen, but we _could_ modify the behavior you saw eg. by modifying https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/request.py#L138 slightly so that passing a `Request` to `Request` uses the only underlying `HTTPRequest`, rather then ending up with the convoluted `._request._request`.

There might also be some cases where that'd be helpful if folks are manually constructing `Request` instances in test cases and passing them to the view.

I'm slightly unclear _why_ you'd need to access the underlying `HTTPRequest` instance tho, as the proxying behavior we provide should generally ensure that it's not needed.

I think this is related to a use case I'm trying to implement which is effectively [batching up data from many views](https://groups.google.com/forum/?fromgroups#!topic/django-rest-framework/39aJuJLpVmw).

If we do nothing else we should at least raise an error in this case.


Resolving patch:
diff --git a/rest_framework/request.py b/rest_framework/request.py
--- a/rest_framework/request.py
+++ b/rest_framework/request.py
@@ -11,7 +11,7 @@
 from __future__ import unicode_literals
 
 from django.conf import settings
-from django.http import QueryDict
+from django.http import HttpRequest, QueryDict
 from django.http.multipartparser import parse_header
 from django.http.request import RawPostDataException
 from django.utils import six
@@ -132,6 +132,12 @@ class Request(object):
 
     def __init__(self, request, parsers=None, authenticators=None,
                  negotiator=None, parser_context=None):
+        assert isinstance(request, HttpRequest), (
+            'The `request` argument must be an instance of '
+            '`django.http.HttpRequest`, not `{}.{}`.'
+            .format(request.__class__.__module__, request.__class__.__name__)
+        )
+
         self._request = request
         self.parsers = parsers or ()
         self.authenticators = authenticators or ()


Test patch:
diff --git a/tests/test_metadata.py b/tests/test_metadata.py
--- a/tests/test_metadata.py
+++ b/tests/test_metadata.py
@@ -9,12 +9,11 @@
     exceptions, metadata, serializers, status, versioning, views
 )
 from rest_framework.renderers import BrowsableAPIRenderer
-from rest_framework.request import Request
 from rest_framework.test import APIRequestFactory
 
 from .models import BasicModel
 
-request = Request(APIRequestFactory().options('/'))
+request = APIRequestFactory().options('/')
 
 
 class TestMetadata:
diff --git a/tests/test_request.py b/tests/test_request.py
--- a/tests/test_request.py
+++ b/tests/test_request.py
@@ -25,6 +25,18 @@
 factory = APIRequestFactory()
 
 
+class TestInitializer(TestCase):
+    def test_request_type(self):
+        request = Request(factory.get('/'))
+
+        message = (
+            'The `request` argument must be an instance of '
+            '`django.http.HttpRequest`, not `rest_framework.request.Request`.'
+        )
+        with self.assertRaisesMessage(AssertionError, message):
+            Request(request)
+
+
 class PlainTextParser(BaseParser):
     media_type = 'text/plain'