【问题标题】:What information do Python/Django decorators have access to?Python/Django 装饰器可以访问哪些信息?
【发布时间】:2013-01-15 18:36:41
【问题描述】:

我在我们的代码中做了一些重构。 @render_to_json 装饰器在内部调用 is_logged_in 方法。我将其删除,而是简单地添加另一个显式 @login_required 装饰器。

问题是我们的一些方法是通过 AJAX 调用的,并且期望得到 {"status": "logged_out"} 的 json 响应,然后它们会对其进行操作。所以我需要改变我们的 login_required 方法以某种方式检查两件事之一。

  • 此方法是否通过 AJAX 调用,可能检测到 XMLHttpRequest 标头
  • 是否也为此请求调用了 render_to_json 装饰器。我们的想法是,如果login_required 方法知道请求需要 json,那么它可以返回 json 数据包,否则正常重定向。

更新添加第三个选项。

  • 在任何情况下,带有@render_to_json 装饰器的方法,@login_required 装饰器在它之前被引用。如果用户已注销,@login_required 方法将返回 HttpResponseRedirect。在@render_to_json 方法中,如何检查 login_required 方法的返回类型并做出适当响应?

想法?有问题吗?

我应该补充一点,我对 Python 也很陌生,所以我可能会遗漏一些基本的东西。如果有,帮我学习一下?

更新

我将继续在此处添加两个装饰器以供参考。

def render_to_json(fn):

    @wraps(fn)
    def inner(request, *args, **kwargs):
        result = fn(request, *args, **kwargs)
        return HttpResponse(json.dumps(result), mimetype='application/json')

    return inner

def login_required(func):
    @wraps(func)
    def _decorator(request, *args, **kwargs):
        if not is_logged_in(request):
            from apps.core.extendedLogging import ExtendedLogging
            ExtendedLogging.log("In login req'd: it appears that the user is not logged in", request)
            request.session['login_referrer_uri'] = request.build_absolute_uri()
            return HttpResponseRedirect(settings.LOGIN_URL)
        return func(request, *args, **kwargs)
    return _decorator

【问题讨论】:

  • 装饰器可以访问调用它装饰的函数的所有参数,所以我不确定我是否理解第一个要点。
  • 大卫。请记住,我通常是 Python 新手。我怀疑会是这样,但不确定。根据这篇文章,我将使用 request.META 来访问所有请求标头? stackoverflow.com/questions/3889769/…
  • 我会专门寻找这个请求头X-Requested-With XMLHttpRequest

标签: python django http-headers decorator


【解决方案1】:

装饰者可以访问“装饰者”正在接收的所有数据:

def method_decorator(operation):
    """
    On this case operation = view_method
    """
    def wrapper(*args, **kwargs):
        """
        Receives all arguments the requested operation would receive
        """
            request = args[0]
            param = args[1]
            more_param = args[2]

            return operation(request, param, more_param)
    return wrapper

@method_decorator
def view_method(request, param, more_param):
    #something

所以,当你调用“view_method”时,首先你会抛出“method_decorator”,然后它会调用“view_method”。

现在,在装饰器中,您可以验证您需要的任何内容并传递新信息,例如:

def wrapper(*args, **kwargs):
        ...
        if some_condition:
            request.new_content = new_content
        return operation(request, param, more_param)
return wrapper

这将允许您在请求的 view_method 上接收 new_content:

@method_decorator
def view_method(request, param, more_param):
    new_content = request.new_content

而且,希望 view_method 现在知道该做什么。

您也可以使用相同的方法将数据从装饰器冒泡到装饰器。

【讨论】:

  • 谢谢。非常彻底的回应...感谢您的时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-07
  • 1970-01-01
  • 2011-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多