python - 检查基于 Django 类的 View 中的 View 方法参数名称

标签 python django django-class-based-views

我在我的 Django 项目中创建了一个装饰器,用于将参数值注入(inject)到装饰方法的参数中。

我通过使用 inspect.getargspec 检查方法中存在哪些参数并将它们放在 kwargs 中来执行此操作。否则,由于方法中的参数数量不正确,我会收到错误消息。

虽然这在单个 View 方法中可以正常工作,但在涉及 Django 的基于类的 View 时它会失败。

我相信这可能是因为装饰器是在类级别使用 @method_decorator 应用于 dispatch 方法而不是单独的 getpost 方法。

我是 Python 新手,可能忽略了这里明显的一些东西。

有没有更好的方法来做我正在做的事情?是否可以在基于类的 View 中获取方法参数名称?

我正在使用 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

基于类的 View

@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 的基于类的 View 。您需要在 url 配置中应用装饰器,或者将装饰器应用到 dispatch 方法。

编辑: 我已经发布了与我正在探索的解决方法相关的代码,将参数名称作为参数传递给装饰器。

最佳答案

我找到了这篇文章:Function decorators with parameters on a class based view in Django

这可能会为您的问题提供答案:

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" docs,我们可以看到如下内容:

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_decoratorname 参数以匹配将应用于的方法:

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):
        ...

关于python - 检查基于 Django 类的 View 中的 View 方法参数名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43887699/

相关文章:

python - 如何在运行时将字符串转换为格式化字符串文字?

python - 如何在 django admin 中对模型进行分组?

django - 在 Heroku 上部署 Django/静态文件的正确方法

django - Stripe 客户是在没有信用卡信息的情况下创建的

python - 将参数传递给 FormView Django 中的表单

python - 窗体的干净方法没有被调用

python - 在 python 中匹配先前定义的组

python - 如何在 Python 中表示无限数?

django - Ajax 和 ModelForm 更新模型

python - XML 子元素中的变量