【问题标题】:Django Rest Framework APIRequestFactory request object has no attribute 'query_params'Django Rest Framework APIRequestFactory 请求对象没有属性'query_params'
【发布时间】:2015-02-09 23:59:22
【问题描述】:

假设我有这个 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'>

【问题讨论】:

    标签: django django-rest-framework


    【解决方案1】:

    参考汤姆的解决方案,DummyView()(request) 会报错:

    TypeError: 'DummyView' object is not callable
    

    相反,应该使用as_view,就像你在urls.py中所做的一样:

    DummyView.as_view()(request)
    

    DRF 的as_view 使用method initialize_request 将Django Request 对象转换为DRF 版本。你可以试试:

    from rest_framework.views import APIView
    APIView().initialize_request(request)
    >>> <rest_framework.request.Request object at 0xad9850c>
    

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

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

    【讨论】:

    • 虽然我接受了 Tom 的回答,因为它在这里直接回答了我的问题,但 initialize_request 提示实际上有很大帮助。
    【解决方案2】:

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

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

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

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

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

    【讨论】:

    • 对我来说:我在基于 django 类的视图中使用了序列化程序并得到了上述异常。原因:非 drf 请求已发送到序列化程序上下文/
    【解决方案3】:

    我意识到这个答案是在提出问题后的一段时间,但它为我解决了这个问题。只需覆盖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
    

    【讨论】:

      猜你喜欢
      • 2017-08-11
      • 2023-03-08
      • 2015-10-15
      • 2019-04-30
      • 2017-03-04
      • 2021-05-02
      • 2018-09-13
      • 2020-12-24
      • 2011-10-13
      相关资源
      最近更新 更多