在基于 Django class 的视图中检查视图方法参数名称
Check view method parameter name in Django class based views
我在我的 Django 项目中创建了一个装饰器,用于将参数值注入到装饰方法的参数中。
我通过使用 inspect.getargspec
检查方法中存在哪些参数并将它们放在 kwargs
中来执行此操作。否则,由于方法中的参数数量不正确,我会收到错误消息。
虽然这在单个视图方法中可以正常工作,但在涉及 Django 的 class 基于视图时它会失败。
我认为这可能是因为装饰器是在 class 级别使用 @method_decorator
应用于 dispatch
方法而不是单独的 get
和 post
方法。
我是 python 新手,可能忽略了一些明显的东西。
有没有更好的方法来完成我正在做的事情?是否可以在基于 class 的视图中获取方法参数名称?
我正在使用 Python 2.7 和 Django 1.11
装饰者
def need_jwt_verification(decorated_function):
@wraps(decorated_function)
def decorator(*args, **kwargs):
request = args[0]
if not isinstance(request, HttpRequest):
raise RuntimeError(
"This decorator can only work with django view methods accepting a HTTPRequest as the first parameter")
if AUTHORIZATION_HEADER_NAME not in request.META:
return HttpResponse("Missing authentication header", status=401)
jwt_token = request.META[AUTHORIZATION_HEADER_NAME].replace(BEARER_METHOD_TEXT, "")
try:
decoded_payload = jwt_service.verify_token(jwt_token)
parameter_names = inspect.getargspec(decorated_function).args
if "phone_number" in parameter_names or "phone_number" in parameter_names:
kwargs["phone_number"] = decoded_payload["phone"]
if "user_id" in parameter_names:
kwargs["user_id"] = decoded_payload["user_id"]
if "email" in parameter_names:
kwargs["email"] = decoded_payload["email"]
return decorated_function(*args, **kwargs)
except JWTError as e:
return HttpResponse("Incorrect or expired authentication header", status=401)
return decorator
基于 class 的视图
@method_decorator([csrf_exempt, need_jwt_verification], name="dispatch")
class EMController(View):
def get(self, request, phone_number, event_id):
data = get_data()
return JsonResponse(data, safe=False)
def post(self, request, phone_number, event_id):
return JsonResponse("Operation successful", safe=False)
编辑:
在方法级别应用装饰器的明显解决方案不适用于 Django 基于 class 的视图。您需要在 url 配置处应用装饰器,或者将装饰器应用在 dispatch 方法上。
编辑:
我已经发布了与我正在探索的解决方法相关的代码,将参数名称作为参数传递给装饰器。
我找到这个 post:
这可能会为您的问题提供答案:
If you want to pass a decorator with parameters, you only need to:
Evaluate the parameters in the decorator-creator function.
Pass the evaluated value to @method_decorator
.
上面提到的以及在考虑的链接答案中提供的代码,您应该:
injectables=[inject_1, inject_2, ..., inject_n]
decorators = [csrf_exempt, need_jwt_verification(injectables)]
@method_decorator(decorators, name="dispatch")
class EMController(View):
...
出于遗留原因,将我之前的错误答案留在此处,请勿在家中(或任何地方,在 django 中,就此而言!!)
如果我们观察 "decorating a class" 文档,我们可以看到以下内容:
Or, more succinctly, you can decorate the class instead and pass the name of the method to be decorated as the keyword argument name:
因此您必须更改 @method_decorator
的 name
参数以匹配将适用于的方法:
decorators = [csrf_exempt, need_jwt_verification(injectables=[])]
@method_decorator(decorators, name='get')
@method_decorator(decorators, name='post')
class EMController(View):
就我个人而言,我更喜欢将我的装饰器放在它们将应用到的特定方法之上:
class EMController(View):
@method_decorator(decorators)
def get(self, request, phone_number, event_id):
...
@method_decorator(decorators)
def post(self, request, phone_number, event_id):
...
在目前的图书馆状态下,我想要的似乎是不可能的。这就是我最终采用的方法。
parameter_names = inspect.getargspec(decorated_function).args
if "phone_number" in parameter_names or "phone_number" in injectables:
kwargs["phone_number"] = decoded_payload["phone"]
if "user_id" in parameter_names:
kwargs["user_id"] = decoded_payload["user_id"]
if "email" in parameter_names:
kwargs["email"] = decoded_payload["email"]
request.__setattr__("JWT", {})
request.JWT["phone_number"] = decoded_payload["phone"]
request.JWT["user_id"] = decoded_payload["user_id"]
request.JWT["email"] = decoded_payload["email"]
此装饰器将按预期自动填充基于方法的视图中的参数。
但它也会向请求对象注入一个 JWT
属性,供基于 class 的视图使用。像 request.GET
和 request.POST
.
我在我的 Django 项目中创建了一个装饰器,用于将参数值注入到装饰方法的参数中。
我通过使用 inspect.getargspec
检查方法中存在哪些参数并将它们放在 kwargs
中来执行此操作。否则,由于方法中的参数数量不正确,我会收到错误消息。
虽然这在单个视图方法中可以正常工作,但在涉及 Django 的 class 基于视图时它会失败。
我认为这可能是因为装饰器是在 class 级别使用 @method_decorator
应用于 dispatch
方法而不是单独的 get
和 post
方法。
我是 python 新手,可能忽略了一些明显的东西。
有没有更好的方法来完成我正在做的事情?是否可以在基于 class 的视图中获取方法参数名称?
我正在使用 Python 2.7 和 Django 1.11
装饰者
def need_jwt_verification(decorated_function):
@wraps(decorated_function)
def decorator(*args, **kwargs):
request = args[0]
if not isinstance(request, HttpRequest):
raise RuntimeError(
"This decorator can only work with django view methods accepting a HTTPRequest as the first parameter")
if AUTHORIZATION_HEADER_NAME not in request.META:
return HttpResponse("Missing authentication header", status=401)
jwt_token = request.META[AUTHORIZATION_HEADER_NAME].replace(BEARER_METHOD_TEXT, "")
try:
decoded_payload = jwt_service.verify_token(jwt_token)
parameter_names = inspect.getargspec(decorated_function).args
if "phone_number" in parameter_names or "phone_number" in parameter_names:
kwargs["phone_number"] = decoded_payload["phone"]
if "user_id" in parameter_names:
kwargs["user_id"] = decoded_payload["user_id"]
if "email" in parameter_names:
kwargs["email"] = decoded_payload["email"]
return decorated_function(*args, **kwargs)
except JWTError as e:
return HttpResponse("Incorrect or expired authentication header", status=401)
return decorator
基于 class 的视图
@method_decorator([csrf_exempt, need_jwt_verification], name="dispatch")
class EMController(View):
def get(self, request, phone_number, event_id):
data = get_data()
return JsonResponse(data, safe=False)
def post(self, request, phone_number, event_id):
return JsonResponse("Operation successful", safe=False)
编辑:
在方法级别应用装饰器的明显解决方案不适用于 Django 基于 class 的视图。您需要在 url 配置处应用装饰器,或者将装饰器应用在 dispatch 方法上。
编辑: 我已经发布了与我正在探索的解决方法相关的代码,将参数名称作为参数传递给装饰器。
我找到这个 post:
这可能会为您的问题提供答案:
If you want to pass a decorator with parameters, you only need to:
Evaluate the parameters in the decorator-creator function.
Pass the evaluated value to
@method_decorator
.
上面提到的以及在考虑的链接答案中提供的代码,您应该:
injectables=[inject_1, inject_2, ..., inject_n]
decorators = [csrf_exempt, need_jwt_verification(injectables)]
@method_decorator(decorators, name="dispatch")
class EMController(View):
...
出于遗留原因,将我之前的错误答案留在此处,请勿在家中(或任何地方,在 django 中,就此而言!!)
如果我们观察 "decorating a class" 文档,我们可以看到以下内容:
Or, more succinctly, you can decorate the class instead and pass the name of the method to be decorated as the keyword argument name:
因此您必须更改 @method_decorator
的 name
参数以匹配将适用于的方法:
decorators = [csrf_exempt, need_jwt_verification(injectables=[])]
@method_decorator(decorators, name='get')
@method_decorator(decorators, name='post')
class EMController(View):
就我个人而言,我更喜欢将我的装饰器放在它们将应用到的特定方法之上:
class EMController(View):
@method_decorator(decorators)
def get(self, request, phone_number, event_id):
...
@method_decorator(decorators)
def post(self, request, phone_number, event_id):
...
在目前的图书馆状态下,我想要的似乎是不可能的。这就是我最终采用的方法。
parameter_names = inspect.getargspec(decorated_function).args
if "phone_number" in parameter_names or "phone_number" in injectables:
kwargs["phone_number"] = decoded_payload["phone"]
if "user_id" in parameter_names:
kwargs["user_id"] = decoded_payload["user_id"]
if "email" in parameter_names:
kwargs["email"] = decoded_payload["email"]
request.__setattr__("JWT", {})
request.JWT["phone_number"] = decoded_payload["phone"]
request.JWT["user_id"] = decoded_payload["user_id"]
request.JWT["email"] = decoded_payload["email"]
此装饰器将按预期自动填充基于方法的视图中的参数。
但它也会向请求对象注入一个 JWT
属性,供基于 class 的视图使用。像 request.GET
和 request.POST
.