如何获取Pyramid中add_static_view()的文件路径

2 投票
1 回答
2429 浏览
提问于 2025-04-17 13:04

当我像这样添加一个 static view 时:

cfg = config.Configurator(...)
cfg.add_static_view(name='static', path='MyPgk:static')

# And I want to add a view for 'favicon.ico'.
cfg.add_route(name='favicon', pattern='/favicon.ico')
cfg.add_view(route_name='favicon', view='MyPgk.views.mymodule.favicon_view')

我想要处理那个烦人的默认路径 /favicon.ico,这个路径是浏览器在网页中没有定义时会自动调用的。我想用 http://docs.pylonsproject.org/projects/pyramid_cookbook/en/latest/files.html 上的例子,并修改成:

def favicon_view(request, cache=dict()):
    if (not cache):
        _path_to_MyPkg_static = __WHAT_GOES_HERE__
        _icon = open(os.path.join(_path_to_MyPkg_static, 'favicon.ico')).read()
        cache['response'] = Response(content_type='image/x-icon', body=_icon)
    return cache['response']

因为我无法真正定义例子中的 _here,那么我该如何让它依赖于 request 来在运行时获取实际的完整路径呢?或者我真的需要处理:

_here = os.path.dirname(__file__)
_path_to_MyPkg_static = os.path.join(os.path.dirname(_here), 'static')

并且在我决定重构,把视图放到其他包或子包,或者其他地方时要小心吗?

我想要的功能类似于 request.static_path(),但不是获取 url path,而是获取一个目录路径:

request.static_file_path('static') -> /path/to/site-packages/MyPkg/static

谢谢,

1 个回答

4

你可以使用 pkg_resources 模块来创建与 Python 模块相关的路径,这样就不受获取这些路径的模块的影响。例如:

import pkg_resources
print pkg_resources.resource_filename('os.path', 'static/favicon.ico')
# 'C:\\Python27\\lib\\static\\favicon.ico'

只需将 os.path 替换为你静态文件的父模块即可。

编辑:如果你需要记住 'static' 路由是映射到 'MyPkg:static' 的,那么最简单的方法是在一开始就把它保存在一个字典里:

STATIC_ROUTES = {'static': 'MyPkg:static'}
for name, path in STATIC_ROUTES.iteritems():
    cfg.add_static_view(name=name, path=path)

然后只需简单地获取这个路径:

static_path = STATIC_ROUTES['static']
package, relative_path = static_path.split(':')
icon_path = pkg_resources.resource_filename(
    package, os.path.join(relative_path, 'favicon.ico'))

不过,如果这不可能(例如,你没有访问 cfg 对象的权限),你还是可以获取这个路径,只是过程会比较麻烦。这是一个示例函数,它使用了一些未记录的调用(所以在未来的 Pyramid 版本中可能会改变),并且忽略了一些额外的设置(比如 route_prefix 配置变量):

def get_static_path(request, name):
    from pyramid.config.views import StaticURLInfo
    registrations = StaticURLInfo()._get_registrations(request.registry)
    if not name.endswith('/'):
        name = name + '/'
    route_name = '__%s' % name
    for _url, spec, reg_route_name in registrations:
        print ':', reg_route_name
        if reg_route_name == route_name:
            return spec

在你的情况下,它应该这样工作:

>>> get_static_path(request, 'static')
MyPkg:static/

撰写回答