我想用装饰器装饰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"
}
由于POST
和PUT/DELETE/GET
包含相同的参数,那么PUT/DELETE/GET
次请求会发生什么不同?
答案 0 :(得分:0)
问题是你包装的一些函数接受一个名为request
的参数,而其他函数接受一个名为bundle
的参数,但你的装饰器总是调用该参数request
。当Tastypie的内部尝试传递bundle
关键字参数时,这会导致错误。你的装饰者不知道任何名为bundle
的参数,所以它被收集在**kwargs
中,你的装饰者没有收到request
参数。
我不清楚Django或Tastypie知道request
和bundle之间应该有什么区别。如果它们在不同的名称下是相同的,您可以将该参数转换为kwargs
并让装饰器手动查找名为request
或bundle
的参数。如果参数request
和bundle
表示不同的东西,您可能需要编写两个不同的装饰器来适当地处理它们。