MrT*_*thy 9 python login flask
在我的Flask-App中,我定义了一个这样的视图函数:
@app.route("/some/restricted/stuff")
@login_required
def main():
return render_template("overview.html",
stuff = getstuff() )
Run Code Online (Sandbox Code Playgroud)
装饰器被定义为:
def login_required(something):
@wraps(something)
def wrap(*args, **kwargs):
if "some_admin_name" in session:
return something(*args, **kwargs)
else:
flash("\"You shall not pass!\" - Gandalf")
return redirect(url_for("login"))
return wrap
Run Code Online (Sandbox Code Playgroud)
我基本上只是复制粘贴,因为我发现了一些使用此代码的来源,但没有解释.
很容易理解代码的作用:它允许我使用在app.route()之后和main()之前为每个请求调用的装饰器,允许我执行诸如检查活动登录之类的东西.
所以,作为一个Flask/Python新手,我只想知道这是如何起作用的,尤其是:
- 什么是"某事"的论点?这是请求吗?!
- 什么是args和kwargs(关键字参数?)?
- 为什么我必须在方法中包装一个方法来将其用作装饰器?
- 这只适用于烧瓶吗?还有其他情况可以派上用场吗?
eik*_*ega 24
欢迎使用Python!这是很多很棒的问题.我们一次拿一个.而且,只是一个公平的警告点.这个主题让你的头脑旋转了一段时间才能一起点击.
作为参考,这是你的示例装饰器和正在装饰的函数:
# Decorator Function
def login_required(something):
@wraps(something)
def wrap(*args, **kwargs):
if "some_admin_name" in session:
return something(*args, **kwargs)
else:
flash("\"You shall not pass!\" - Gandalf")
return redirect(url_for("login"))
return wrap
# Function Being Decorated
@app.route("/some/restricted/stuff")
@login_required
def main():
return render_template("overview.html",
stuff = getstuff() )
Run Code Online (Sandbox Code Playgroud)
要回答这个问题,我们首先要回答一下装饰器是什么.根据您正在装饰的对象类型,答案可能会有所不同.在这种情况下,当您正在装饰函数时,您可以将装饰器视为允许程序员修改另一个函数的行为的方法/函数.
有了这个,我们可以回答你的问题."something"是你要装饰的功能/方法. 是的,它是一个将另一个函数作为参数的函数.
让我们更改装饰器函数的语言,使其更清晰:
def login_required(function_to_wrap):
@wraps(function_to_wrap)
def wrap(*args, **kwargs):
if "some_admin_name" in session:
return function_to_wrap(*args, **kwargs)
else:
flash("\"You shall not pass!\" - Gandalf")
return redirect(url_for("login"))
return wrap
Run Code Online (Sandbox Code Playgroud)
简而言之,这是Python允许参数程序员编写采用可变数量的关键字和非关键字参数的函数/方法的方法.
通常,在编写函数时,请明确指定参数.例如:
def add_these_numbers(number_1, number_2):
return number_1 + number_2
Run Code Online (Sandbox Code Playgroud)
然而,这不是唯一的做事方式.您也可以使用*args或**kargs来完成同样的事情:
def add_these_numbers(*args):
return args[0] + args[1]
def add_these_numbers_too(**kwargs):
return kwargs['first_number'] + kwargs['second_number']
Run Code Online (Sandbox Code Playgroud)
因为它与您的问题有关,*args/**kwargs通常用于装饰器,因为装饰器通常应用于各种方法,这些方法将采用各种各样的参数.
使用args/**kwargs允许装饰器方法通过装饰器函数传递方法最初需要的方法. 如果这让你头晕,请告诉我,我会尽力澄清.
让我们改变main(),以便更清楚:
# Function Being Decorated
@app.route("/some/restricted/stuff")
@login_required
def main(html_template):
return render_template(html_template, stuff = getstuff())
Run Code Online (Sandbox Code Playgroud)
在我看来,这是理解装饰器中最棘手的部分. 关键是要理解装饰器的核心是接管原始功能的名称.
理解这一点的最简单方法是在不使用方便的@语法的情况下应用装饰器.以下是等效的:
@login_required
def main():
....
main = login_required(main)
Run Code Online (Sandbox Code Playgroud)
坚持你的马匹,这就是真棒! 这两个代码片段告诉Python的是,"'main'一词应该不再引用main()函数,而是在将原始main()函数作为参数传递给结果login_required()函数时.
是.对main()的调用现在引用对login_required(main())的调用结果.这也是login_required返回嵌套函数的原因.新的main()必须仍然是一个函数,就像旧函数一样.
不同之处在于,现在新的main函数实际上是wrap()的一个实例,由传递给login_required()的参数自定义.
所以...有效的main()现在等效于以下内容:
def main(*args, **kwargs):
if "some_admin_name" in session:
return predecorator_main_function(*args, **kwargs)
else:
flash("\"You shall not pass!\" - Gandalf")
return redirect(url_for("login"))
Run Code Online (Sandbox Code Playgroud)
当然不!装饰器是内置于Python中的众多超级功能之一.在您不想创建其他函数以避免代码重复时,想要对现有函数/方法进行修改(在我看来相对较小)的任何情况下,装饰器都很有用.
| 归档时间: |
|
| 查看次数: |
3743 次 |
| 最近记录: |