Django Rest Framework APIRequestFactory请求对象没有属性" query_params'

时间:2015-02-09 23:59:23

标签: django django-rest-framework

让我说我有这个APIView

class Dummy(APIView):
    def get(self, request):
        return Response(data=request.query_params.get('uuid'))

要测试它,我需要创建一个请求对象以传递到get函数

def test_dummy(self):
    from rest_framework.test import APIRequestFactory
    factory = APIRequestFactory()
    request = factory.get('/?uuid=abcd')
    DummyView().get(request)

抱怨AttributeError: 'WSGIRequest' object has no attribute 'query_params'

仔细观察,工厂会创建WSGIRequest个实例,而不是DRF版本<class 'rest_framework.request.Request'>

>>> from rest_framework.test import APIRequestFactory
>>> factory = APIRequestFactory()
>>> request = factory.get('/')
>>> request.__class__
<class 'django.core.handlers.wsgi.WSGIRequest'>

3 个答案:

答案 0 :(得分:14)

请参阅Tom的解决方案,DummyView()(request)会引发错误:

TypeError: 'DummyView' object is not callable

相反,应该像使用as_view中的urls.py一样使用DummyView.as_view()(request)

as_view

DRF from rest_framework.views import APIView APIView().initialize_request(request) >>> <rest_framework.request.Request object at 0xad9850c> 使用method initialize_request将Django Request对象转换为DRF版本。您可以尝试:

from rest_framework.test import APIClient
client = APIClient()
client.post('/notes/', {'title': 'new idea'}, format='json')

您也可以使用APIClient来运行测试。它还测试URL调度。

{{1}}

答案 1 :(得分:11)

那是对的。目前APIRequestFactory返回一个HttpRequest对象,只有在到达视图层后才会升级到REST框架Request对象。

这反映了您在实际请求中看到的行为,以及所做的事情是如何处理的。呈现JSON,XML或您为测试请求配置的任何其他内容类型。

但是我同意它的令人惊讶的行为,并且在某些时候它可能会返回一个Request对象,而REST框架视图将确保它只对请求执行Request升级那个HttpRequest的实例。

您需要做的是实际上调用视图,而不是调用.get()方法......

factory = APIRequestFactory()
request = factory.get('/?uuid=abcd')
view = DummyView.as_view()
response = view(request)  # Calling the view, not calling `.get()`

答案 2 :(得分:0)

我知道这个问题是在提出问题后的一段时间,但是它为我解决了这个问题。只需重写APIRequestFactory类,如下所示。

# Override APIRequestFactory to add the query_params attribute.
class MyAPIRequestFactory(APIRequestFactory):

    def generic(self, method, path, data='',
                content_type='application/octet-stream', secure=False,
                **extra):
        # Include the CONTENT_TYPE, regardless of whether or not data is empty.
        if content_type is not None:
            extra['CONTENT_TYPE'] = str(content_type)

        request = super(MyAPIRequestFactory, self).generic(
            method, path, data, content_type, secure, **extra)
        request.query_params = request.GET
        return request