【问题标题】:Pyramid decorator chaining金字塔装饰器链接
【发布时间】:2026-01-04 10:40:01
【问题描述】:

在我的金字塔应用程序中,我试图通过装饰视图功能来实现授权。
当我使用 config.scan() 函数时,没有添加任何视图,但是如果我使用 config.add_view() 明确添加它们,一切正常。

我有两个文件,一个定义了所有的视图函数(views.py)

from pyramid.view import view_config
from pyramid.response import Response

from functools import wraps

def authorized(func):    #decorator difnition
    @wraps(func)
    def new_func(request):
        if(request.cookies.get('user')):   # authorization
            return func(request)
        else:
            return Response('not authirised')
    return new_func



@view_config(route_name='hello')           # view function being decorated
@authorized
def privileged_action(request):
    return Response('Hello %(name)s!' % request.matchdict)

还有另一个文件来创建导入views.py的服务器(serve.py)

from wsgiref.simple_server import make_server
from pyramid.config import Configurator

from views import privileged_action

if __name__ == '__main__':
    config = Configurator()
    config.add_route('hello', '/hello/{name}')
    # config.add_view(privileged_action, route_name='hello')   # This works
    config.scan()                                              # This doesn't work
    app = config.make_wsgi_app()
    server = make_server('0.0.0.0', 8080, app)
    server.serve_forever()

如果我使用“http://localhost:8080/hello/a”访问,则会出现 404 not found 错误
为什么这不起作用?
有什么办法可以做到这一点?

【问题讨论】:

  • 如果您没有 @authorized 装饰器,@view_config(route_name='hello') 是否工作?
  • 是的。在上面的代码中删除 config.scan() 行并取消注释 config.add_view(privileged_action, route_name='hello') 它将按预期工作。
  • 请注意,Pyramid 具有预先构建的身份验证/权限框架,特别是 @view_config 具有 permission 属性,如果设置正确,它将完全按照您的装饰器正在做的事情做,只会更好。 . 只是感觉你正在重新发明自行车......
  • @Sergey 我也在使用装饰器来执行其他一些常见任务。但是,我将研究内置的身份验证/权限框架

标签: python pyramid


【解决方案1】:

您的带有装饰器的代码看起来不错。

Configurator.scan() 的文档说明了它的第一个参数:

package 参数应该是 Python 包或模块对象(或引用此类包或模块的点划线 Python 名称)。如果 package 为 None,则使用调用者的 package。

所以请确保您正在使用config.scan(views),以便让您的网络应用动态添加您的视图。

【讨论】:

  • 谢谢。这似乎可以解决问题。知道为什么 config.scan() 不适用于装饰视图功能吗?
  • 究竟是什么不工作,什么是?现在一切都应该正常了。
  • 如果您说一切正常(包括修饰函数时),但只有在您不将参数传递给 scan 时才不起作用,那是因为 scan 没有“扫描”正确的位置,直到你明确告诉它。它只扫描当前文件。而不是您的views 文件。
  • 那为什么config.scan() 会从views 中添加所有未修饰的视图函数,为什么它不能只对修饰视图起作用?
  • 出于好奇,去掉@authorized这个装饰器还能用吗?