Python装饰器Error- decorated_view()至少需要2个参数(给定1个)"

时间:2014-06-03 04:28:35

标签: python django python-decorators

我想用装饰器装饰Django中的视图。基本上我想在访问API的任何端点URL之前,使用auth-token密钥对用户进行身份验证以授权其凭据: -

这是我的代码: -

class XYZResource(ModelResource):

    class Meta:
        queryset = XYZ.objects.all()
        resource_name = 'xyz'
        allowed_methods = ['get','post','delete','put']

    @roles_accepted('admin','staff')
    def obj_get(self, bundle, **kwargs):
        ..............

    @roles_accepted('admin','staff')
    def get_object_list(self, request): 
        ......


    @roles_accepted('admin','staff')
    def obj_create(self, bundle, **kwargs):
         ......

    @roles_accepted('admin','staff')
    def obj_update(self, bundle, **kwargs):
             ......


    @roles_accepted('admin','staff')
    def obj_delete(self, bundle, **kwargs):
             ......

这是我的装饰者: -

def roles_accepted(*roles):
    def wrapper(fn):
        def decorated_view(self,request,*args, **kwargs):
            if check_role(request) in roles  or check_role(request.request) in roles: # for POST,PUT,DELETE where bundle is passed, 
                return fn(self,request,*args, **kwargs)                               # auth_token is contained in bundle.request
            raise ImmediateHttpResponse(create_json_response({"error": "Unauthorized user"}, HttpUnauthorized)) 
        return decorated_view
    return wrapper

我遇到的错误是当我请求POST/GET-ALL时,它可以正常工作,但是当我执行“GET / DELETE / PUT'请求,它说: -

{
  "error_message": "decorated_view() takes at least 2 arguments (1 given)",
  "traceback": "Traceback (most recent call last):\n\n  File \"/usr/local/lib/python2.7/dist-packages/tastypie/resources.py\", line 195, in wrapper\n    response = callback(request, *args, **kwargs)\n\n  File \"/usr/local/lib/python2.7/dist-packages/tastypie/resources.py\", line 435, in dispatch_detail\n    return self.dispatch('detail', request, **kwargs)\n\n  File \"/usr/local/lib/python2.7/dist-packages/tastypie/resources.py\", line 458, in dispatch\n    response = method(request, **kwargs)\n\n  File \"/usr/local/lib/python2.7/dist-packages/tastypie/resources.py\", line 1408, in put_detail\n    updated_bundle = self.obj_update(bundle=bundle, **self.remove_api_resource_names(kwargs))\n\nTypeError: decorated_view() takes at least 2 arguments (1 given)\n"
}

由于POSTPUT/DELETE/GET包含相同的参数,那么PUT/DELETE/GET次请求会发生什么不同?

1 个答案:

答案 0 :(得分:0)

问题是你包装的一些函数接受一个名为request的参数,而其他函数接受一个名为bundle的参数,但你的装饰器总是调用该参数request。当Tastypie的内部尝试传递bundle关键字参数时,这会导致错误。你的装饰者不知道任何名为bundle的参数,所以它被收集在**kwargs中,你的装饰者没有收到request参数。

我不清楚Django或Tastypie知道request和bundle之间应该有什么区别。如果它们在不同的名称下是相同的,您可以将该参数转换为kwargs并让装饰器手动查找名为requestbundle的参数。如果参数requestbundle表示不同的东西,您可能需要编写两个不同的装饰器来适当地处理它们。