为什么我的装饰器打破了这个Flask-Login端点? [英] Why is my decorator breaking for this Flask-Login endpoint?

查看:254
本文介绍了为什么我的装饰器打破了这个Flask-Login端点?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经想出了如何使Flask-Login根据LDAP查找对用户进行身份验证。现在我想给组合添加一些授权 - 也就是说,如果用户已经登录属于正确的组,则只允许访问某些端点。



我不确定这是否是正确的方法,但是我认为我可以添加装饰到端点:$ b​​
$ b

 @ app.route('/ top_secret')
@authorize
@login_required
def top_secret():
return render_template(top_secret .html)

和(现在)创建一个完整的传递装饰器:


$ b $ pre $ def $ author $ c $ def b $ b $ def $ newfunc(* args,** kwargs)
return func(* args ,** kwargs)
return newfunc

但是运行这个错误提示:

  werkzeug.routing.BuildError:无法为端点top_secret构建网址。 

运行时没有使用@authorize装饰工作正常。



所以我不确定我出错的地方。我不能用这种方式装饰端点吗?如果不是,授权步骤应该在哪里进行? (这个必须在@login_required完成之后才能完成)

解决方案

啊,是的,超级简单!

 来自functools import wrapps 


def authorize(func):
@wrap(func)
def newfunc(* args,** kwargs):
返回func(* args,** kwargs)
返回newfunc

要理解为什么需要 wrapps ,您可以这样做:

  print(top_secret)

一次与包装,一次没有。有了wrap,你会看到类似这样的东西:

 <函数top_secret 0x7ff165150840> 

没有它,你会看到:

 < function authorize。< locals> .newfunc at 0x7f81b8456840> 

包装文档是非常好的,但基本上,当你包装一个函数默认情况下,你会失去文档字符串,属性等等。所以你失去了你的函数的 app.route 装饰,所以Flask无法弄清楚如何构建URL。



通过在那里添加 wraps 装饰器,你可以恢复 app.route 对你的函数做的所有事情,烧瓶可以创建你的路线。


I've figured out how to make Flask-Login authenticate a user based on an LDAP lookup. Now I'd like to add some authorization to the mix - that is, only allow access to certain endpoints if a user has both logged in and belongs to the right groups.

I'm not sure if this is the right way to do it, but I thought I could just add a decoration to an endpoint:

@app.route('/top_secret')
@authorize
@login_required
def top_secret():
    return render_template("top_secret.html")

and (for now) make a completely pass-through decorator:

def authorize(func):
    def newfunc(*args, **kwargs):
        return func(*args, **kwargs)
    return newfunc

But running this gives the error:

werkzeug.routing.BuildError: Could not build url for endpoint 'top_secret'.

while running it without the @authorize decorator works fine.

So I'm not sure where I went wrong. Can I not decorate endpoints in this way? And if not, where should the authorization step take place? (it would have to take place after @login_required has finished what it needs to do)

解决方案

Ah, yeah, super simple!

from functools import wraps


def authorize(func):
    @wraps(func)
    def newfunc(*args, **kwargs):
        return func(*args, **kwargs)
    return newfunc

To understand why you need wraps, you can do this:

 print(top_secret)

Once with wraps, and once without. With wraps, you'll see something like this:

<function top_secret at 0x7ff165150840>

Without it, you'll see:

<function authorize.<locals>.newfunc at 0x7f81b8456840>

The documentation for wraps is really good, but basically when you wrap a function by default you lose the docstrings, and attributes, and all the rest. So you lose the app.route decoration for your function, so Flask can't figure out how to build the URL.

By adding the wraps decorator on there, you restore everything that app.route did to your function, and Flask can create your route.

这篇关于为什么我的装饰器打破了这个Flask-Login端点?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆