-
-
Notifications
You must be signed in to change notification settings - Fork 6.9k
APIRequestFactory does not return a rest_framework.request.Request object #3608
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
If your view doesn't go through the DRF view, you won't have a DRF's request. You should therefore not use anything specific to DRF but fallback to Django's default for both your view and the request factory. |
In this case, I'm trying to test a function that handles a request that is normally passed to it via a DRF view. In my unit tests, I'd like to be able to skip the view part (that also deals with serialization and other things) and just test the function with a specific request input so that I can do granular tests of just that piece of functionality (i.e. a unit test). I understand the principle of "if it doesn't go through a DRF view, then don't use DRF features", but I do think it's at least a little unexpected that DRF's APIRequestFactory doesn't return a DRF request. Since this issue is already closed, I assume you have a strong opinion about this and consider it a non-issue. For future reference, I just ended up monkey patching the requests returned by APIRequestFactory so that they behave like DRF requests for the fields I need. |
@jorisroovers APIFactory returns a django request because it'll go through the DRF processes of authentication, permissions, content management and so on which will turns the request into a DRF's one.
|
On a side note, the strong opinion was based on the initial input where I understood you were trying to use a DRF request with a Django regular view. |
@xordoquy Thanks for clarifying :-) |
@xordoquy If you do end up wanting to change something, let me know if you need a helping hand :-) |
I also thought that the purpose of How am i supposed to unittest a decorator that works on @api_view(...)
@my_decorator
def view(request):
# .... Ok, I could create some generic |
@dtheodor either forge the DRF request by yourself or use a Mock. |
To convert into a We don't have any very good options here, given views expect an HTTPRequest object. |
I got this problem in my tests, then inspecting the response object returned in the view and I find the DRF's Request object, for the record I created a new example based on @jorisroovers's code, so it could helps others: def test_foo(self):
def myfunc(request):
# This will raise an exception since the request is of type
# django.core.handlers.wsgi.WSGIRequest
# and not of type rest_framework.request.Request
# -> AttributeError: 'WSGIRequest' object has no attribute 'data'
print request.data
from rest_framework.test import APIRequestFactory
factory = APIRequestFactory()
request = factory.post("/foo", {'key': "val"}) # WSGIRequest
# Add the view call to get response object
view = MyView.as_view(actions={'post': 'detail'})
response = view(request)
response.render()
drf_request = response.renderer_context['request'] # rest_framework.request.Request
myfunc(drf_request) |
I'm having a (possibly) related issue, where my code expects |
@ironyinabox I think that is not related to this issue at all if you are sending form-encoded data then you should expect a if you were expecting a |
I have the same issue: For testing purposes I initialize permission class instance manually and test that of course fails because |
To resolve this issue, you need to wrap the Here's an example of how to correctly use # Imports
from rest_framework.test import APIRequestFactory
from rest_framework.request import Request
from rest_framework.parsers import JSONParser
import json
# Initialize the APIRequestFactory
request_factory = APIRequestFactory()
# Query Param or Data
data = {"key": "value"}
# Example for a GET request
request = request_factory.get('/api/url/', data)
request = Request(request)
# Example for a POST request
json_data = json.dumps(data) # data must be converted to string for POST requests
request = request_factory.post('/api/url/', data=json_data, content_type='application/json')
request = Request(request, parsers=[JSONParser()]) |
The
APIRequestFactory
class is basically a wrapper for Django's RequestFactory, proxying post/get/put/... calls to Django'sRequestFactory.generic()
. As a result, the mock request objects that are returned byAPIRequestFactory
get/post/put/... methods are of the typedjango.core.handlers.wsgi.WSGIRequest
. When passed to a django-rest-framework view, these requests get converted torest_framework.request.Request
objects. While this probably suffices for many use cases, this does cause issues when trying to test code that handles requests directly without going through a django-rest-framework view.In particular, if the code that is being tested tries to access special data members or methods that are specific to
rest_framework.request.Request
such as thedata
member, that code will raise an exception,For example:
The text was updated successfully, but these errors were encountered: