【发布时间】:2017-05-03 13:28:44
【问题描述】:
我正在使用 CherryPy、Mako HTML 模板和 JavaScript 编写一个应用程序。我希望允许将其安装到任何 URL - 也就是说,我希望有人能够将其安装到 http://example.com、http://example.com/app 或 http://this.is.an.example.com/some/application/whatever。我还希望它与 Apache 后面的 WSGI 应用程序或使用 CherryPy 的内置网络服务器一样工作。但是,我无法处理我的模板和 JavaScript 必须使用的 URL。
也就是说,如果我想访问与我的应用程序根目录相关的资源,例如 api/something 或 static/application.js,我如何确保无论我的应用程序的基本 URL 是什么,引用都可以工作?
我最初的、幼稚的解决方案是使用相对 URL,但是当我想在多个端点返回相同的 Mako 模板时,它就停止了工作。也就是说,如果我有一个用于显示项目的模板,也许我想在页面的根目录 (/) 的某处显示该项目,也可能在其他地方显示该项目(比如可能是 /item,也许是 @ 987654328@ 也是)。如果模板中有一个相对 URL,则该 URL 相对于该位置 - 这意味着,由于我的静态 CSS/JS/image 资源仅与 root 相关,因此链接将被破坏/item 和 /username/items 位置的模板。
Mako 模板
我发现我可以在 Mako 模板中将我的 URL 包装在 cherrypy.url() 中,从而解决了这个问题。例如,这个示例模板无论如何都会正确引用/link URL:
<%!
import cherrypy
%>
<a href="${cherrypy.url('/link')}">Click here!</a>
这很好,但是有点麻烦,而且我的模板中的import cherrypy 看起来很奇怪。这是正确的方法吗?有没有更好的办法?如果它是自动的就好了,这样我就不必记得自己包装 URL。
JavaScript
我正在使用 CherryPy 的 tools.staticdir 选项提供静态 .js 文件。这工作正常,但我进行了几次 AJAX 调用,就像我的 Mako 模板中的静态资源一样,URL 是相对于我的应用程序根目录的。例如,如果 CherryPy 公开了一个 /api/something URL,并且我想从 JavaScript 访问它,我如何编写我的 JS 以便无论我的 CherryPy 应用程序安装在哪里都可以访问它?
我的第一个想法是,我可以在模板中添加某种隐藏的 HTML 元素或注释,其中包含不带参数调用的 cherrypy.url() 的值,这将导致我的应用程序的根 URL,并且我可以在尝试发出 HTTP 请求之前,遍历 DOM,获取该值,并将其添加到我想要的任何 URL 之前。好处是这在 JavaScript 中是非常透明的。缺点是当我向应用程序添加越来越多的模板时,很容易忘记包含神奇的隐藏 HTML 元素。我想我可以通过使所有模板依赖于根模板来解决这个问题,但它仍然看起来像一个 hack。
我的第二个想法是将我的 JavaScript 文件本身转换为 Mako 模板,而不是使用 tools.staticdir 来提供它们,并使用我在现有 Mako HTML 模板中使用的相同 cherrypy.url() 方法。这具有一致性的吸引力,并且不需要在我现有的模板中使用神奇的 HTML 元素,但这意味着文件必须经过整个模板渲染过程才能以理论上的速度损失,而且它还感觉有点不对。
还有更好的选择吗?
其他问题
虽然我目前没有这个问题,但我想将来我可能也想在我的静态 CSS 文件中使用与应用程序相关的 URL。
代码异味问题?
我在 Google 和 SO 以及 CherryPy 文档中花了一些时间试图找到解决这个问题的方法,但我没有发现任何东西。这是否表明我正在做一些奇怪的事情,并且有一些模式或最佳实践可以避免我没有遵循的这个问题?
【问题讨论】:
标签: python-3.x cherrypy mako