我以为我会聪明并且编写一个调用会话变量的包装器(很多都存在)并将其添加到需要会话变量的(django)视图中。但是我似乎没有理解变量的范围,或者写错了。
我的包装是:
def s_vars(func_to_decorate):
@wraps(func_to_decorate)
def wrapper(request, *args, **kwargs):
#add all the session variables to kwargs and accessible for the decorated function.
user_obj = request.user
datepicker = request.session['datepicker']
date_format = request.session['date_format']
.........
country = request.session['country']
metric = request.session['metric']
qrydtm = request.session.get("qrydtm",date.today())
result = func_to_decorate(request, *args, **kwargs)
#any post view checks to be done go here
#return to the function to be decorated.
return result
return wrapper
然后对于视图我有类似的东西:
@s_vars
def main(request, template_name='placeholder.html'):
return render_to_response(template_name, RequestContext(request,{
'user':user_obj
}))
但是这会导致在“main”方法中无法访问user_obj的错误。我的理解是这是一个内部函数,因此这个内部函数“main”可以访问“wrapper”方法下列表中的变量。我在这里缺少什么?
答案 0 :(得分:2)
语法
@spam
def ham():
pass
完全等同于语法
def ham():
pass
ham = spam(ham)
这是否澄清了为什么你所做的不起作用?
如果你想把东西从装饰器传递给一个函数,通常的习惯是向函数发送额外的参数。这可能有点icky,因为这意味着看起来正确的argspec实际上不是。
答案 1 :(得分:0)
嵌套函数仅从定义它们的作用域中获取作用域变量,并且绑定在编译时进行。
以后不能添加范围变量,当然也不能使用简单的包装器。
答案 2 :(得分:0)
在内部函数调用时,它只是由外部作用域函数调用,而不是定义。
这种区别(也由解释器与运行时制作)在范围界定中非常重要。看一下s_vars包装器的dis(反汇编)(或相同行为的简化示例)。代码不会针对func_to_decorate
的不同值(这里只是一个值)重新解释。
如果要创建内部函数可用的变量列表,传入的对象可能更有意义。包装器可以确保外部API没有它。