Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/300.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 检查基于Django类的视图中的视图方法参数名称_Python_Django_Django Class Based Views_Class Based Views - Fatal编程技术网

Python 检查基于Django类的视图中的视图方法参数名称

Python 检查基于Django类的视图中的视图方法参数名称,python,django,django-class-based-views,class-based-views,Python,Django,Django Class Based Views,Class Based Views,我在Django项目中创建了一个装饰器,将参数值注入装饰方法的参数中 为此,我使用inspect.getargspec检查方法中存在哪些参数,并将它们放置在kwargs中。否则,由于方法中的参数数量不正确,我会得到一个错误 虽然这在单个视图方法中可以正常工作,但在Django基于类的视图中却失败了 我相信这可能是因为decorator是在类级别使用@method\u decorator应用于dispatch方法,而不是单独的get和post方法 我是python新手,可能忽略了一些显而易见的东西

我在Django项目中创建了一个装饰器,将参数值注入装饰方法的参数中

为此,我使用
inspect.getargspec
检查方法中存在哪些参数,并将它们放置在
kwargs
中。否则,由于方法中的参数数量不正确,我会得到一个错误

虽然这在单个视图方法中可以正常工作,但在Django基于类的视图中却失败了

我相信这可能是因为decorator是在类级别使用
@method\u decorator
应用于
dispatch
方法,而不是单独的
get
post
方法

我是python新手,可能忽略了一些显而易见的东西

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

我正在使用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
基于类的视图

@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)
编辑:

在方法级别应用decorator的明显解决方案不适用于Django的基于类的视图。您需要在url配置中应用decorator,或者将decorator应用于dispatch方法

编辑: 我发布了与我正在探索的解决方案相关的代码,将参数名作为参数传递给decorator。

我发现这篇文章:

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

如果要传递带参数的装饰器,只需:

  • 计算decorator creator函数中的参数

  • 将计算值传递给
    @method\u decorator

根据上述内容和考虑中的链接答案中提供的代码,您应该:

injectables=[inject_1, inject_2, ..., inject_n]
decorators = [csrf_exempt, need_jwt_verification(injectables)]

@method_decorator(decorators, name="dispatch")
class EMController(View):
    ...

由于遗留的原因,将我以前的错误答案留在这里,不要在家里(或者在django的任何地方)尝试这个方法!!)

如果我们观察这些文件,我们可以看到以下内容:

或者,更简洁地说,您可以修饰类而不是,并将要修饰的方法的名称作为关键字参数名称传递:

因此,您必须更改
@method\u 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):
        ...
就我个人而言,我更喜欢将我的装饰师置于他们将应用的特定方法之上:

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
属性,供基于类的视图使用。例如
request.GET
request.POST

在您面临问题的地方发布代码。我认为它没有多大用处。但是当然…我试过你的代码,它工作得很好!那么,你能给出一些细节吗?它失败的原因是什么?根据测试场景,它可能已经工作了,但是有一个问题我正试图解决:)请更详细地阅读这个问题。如果有什么不清楚的地方,请告诉我。谢谢你的回答,但是Django的基于类的视图并不是这样。不能在方法级别应用装饰程序。它们需要应用于
dispatch
方法。@Thihara我在搜索中找到了一个可能的答案,因此,我已编辑了我的答案,请看一看!将参数传递到decorators也是我最后的选择,但我更喜欢检测参数名的黑魔法方法:)最终决定采用另一种方法。不过你可以得到赏金:)