【问题标题】:is there a better way to handle index.html with Tornado?有没有更好的方法来使用 Tornado 处理 index.html?
【发布时间】:2013-01-01 08:15:53
【问题描述】:


我想知道是否有更好的方法来使用 Tornado 处理我的 index.html 文件。

我使用 StaticFileHandler 处理所有请求,并使用特定的 MainHandler 来处理我的主要请求。如果我只使用 StaticFileHandler 我得到一个 403: Forbidden 错误

GET http://localhost:9000/
WARNING:root:403 GET / (127.0.0.1):  is not a file

我现在的情况:

import os
import tornado.ioloop
import tornado.web
from  tornado import web

__author__ = 'gvincent'

root = os.path.dirname(__file__)
port = 9999

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        try:
            with open(os.path.join(root, 'index.html')) as f:
                self.write(f.read())
        except IOError as e:
            self.write("404: Not Found")

application = tornado.web.Application([
    (r"/", MainHandler),
    (r"/(.*)", web.StaticFileHandler, dict(path=root)),
    ])

if __name__ == '__main__':
    application.listen(port)
    tornado.ioloop.IOLoop.instance().start()

【问题讨论】:

  • 最好把r"/"r"/(.*)"换成r"/$"r"/(.*)$"

标签: python tornado


【解决方案1】:

无需显式添加StaticFileHandler;只需指定 static_path,它将为这些页面提供服务。

您是正确的,您需要一个 MainHandler,因为某些原因 Tornado 不会提供 index.html 文件,即使您将文件名附加到 URL。

在这种情况下,对您的代码稍作修改应该对您有用:

import os
import tornado.ioloop
import tornado.web
from tornado import web

__author__ = 'gvincent'

root = os.path.dirname(__file__)
port = 9999

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.render("index.html")

application = tornado.web.Application([
    (r"/", MainHandler),
    ], template_path=root,
    static_path=root)

if __name__ == '__main__':
    application.listen(port)
    tornado.ioloop.IOLoop.instance().start()

【讨论】:

  • 我无法使用此解决方案在我的根文件夹中提供 *.html 文件。我也需要这些文件的处理程序。
  • 您使用的是什么版本的 Tornado?我测试了您的原始答案和我的答案,每个都可以提供任意 *.html 文件。我正在使用 Tornado version = "2.4.post1"version_info = (2, 4, 0, 1)(在 __init__.py 中找到)。
  • version = "2.4.1" version_info = (2, 4, 1, 0) 我用的是同一个版本
  • 这些映射到 /static/
【解决方案2】:

感谢之前的回答,这是我更喜欢的解决方案:

import Settings
import tornado.web
import tornado.httpserver


class Application(tornado.web.Application):
    def __init__(self):
        handlers = [
            (r"/", MainHandler)
        ]
        settings = {
            "template_path": Settings.TEMPLATE_PATH,
            "static_path": Settings.STATIC_PATH,
        }
        tornado.web.Application.__init__(self, handlers, **settings)


class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.render("index.html")


def main():
    applicaton = Application()
    http_server = tornado.httpserver.HTTPServer(applicaton)
    http_server.listen(9999)

    tornado.ioloop.IOLoop.instance().start()

if __name__ == "__main__":
    main()

和 Settings.py

import os
dirname = os.path.dirname(__file__)

STATIC_PATH = os.path.join(dirname, 'static')
TEMPLATE_PATH = os.path.join(dirname, 'templates')

【讨论】:

  • 是否可以通过刷新浏览器而不重新启动应用程序来查看您对index.html 的更改?
  • @xuan 我不明白你要我做什么?
  • 对不起,应该更清楚。假设在开发应用程序期间,您对index.html 进行了更改,并且您希望从浏览器中查看更改。如果index.html 是一个渲染的模板而不是一个静态文件,你能通过刷新页面看到变化吗?
  • 当然有 tornado.autoreload :tornadoweb.org/en/stable/autoreload.html
  • 注意绝对路径,不是相对静态路径!
【解决方案3】:

改用此代码

class IndexDotHTMLAwareStaticFileHandler(tornado.web.StaticFileHandler):
    def parse_url_path(self, url_path):
        if not url_path or url_path.endswith('/'):
            url_path += 'index.html'

        return super(IndexDotHTMLAwareStaticFileHandler, self).parse_url_path(url_path)

现在在您的应用程序中使用该类而不是普通的 StaticFileHandler... 工作完成了!

【讨论】:

    【解决方案4】:

    原来 Tornado 的 StaticFileHandler 已经包含 默认文件名 功能。

    Tornado 版本 1.2.0 中添加了以下功能: https://github.com/tornadoweb/tornado/commit/638a151d96d681d3bdd6ba5ce5dcf2bd1447959c

    要指定默认文件名,您需要将“default_filename”参数设置为 WebStaticFileHandler 初始化的一部分。

    更新您的示例:

    import os
    import tornado.ioloop
    import tornado.web
    
    root = os.path.dirname(__file__)
    port = 9999
    
    application = tornado.web.Application([
        (r"/(.*)", tornado.web.StaticFileHandler, {"path": root, "default_filename": "index.html"})
    ])
    
    if __name__ == '__main__':
        application.listen(port)
        tornado.ioloop.IOLoop.instance().start()
    

    这处理根请求:

    • / -> /index.html

    子目录请求:

    • /tests/ -> /tests/index.html

    并且似乎可以正确处理目录的重定向,这很好:

    • /tests -> /tests/index.html

    【讨论】:

    • 我可以在这些 .html 文件中使用模板标签吗?
    • 这花了我大约 5 个小时才真正找到这个惊人的答案,万分感谢!
    【解决方案5】:

    我一直在尝试这个。不要使用渲染,它会增加解析模板的开销,并且会在静态 html 中的模板类型字符串上出错。我发现这是最简单的方法。 Tornado 正在 regex 中寻找捕获括号,只需给它一个空捕获组。

    import os
    import tornado.ioloop
    import tornado.web
    
    root = os.path.dirname(__file__)
    port = 9999
    
    application = tornado.web.Application([
        (r"/()", tornado.web.StaticFileHandler, {"path": root, "default_filename": "index.html"})
    ])
    

    这具有将 / 解析为 index.html 的效果,还可以避免不需要的解析,例如 /views.html 到 static_dir/views.html

    【讨论】:

      【解决方案6】:

      这对我有用From the tornado docs

      要在请求目录时自动提供类似index.html 的文件,请在应用程序设置中设置static_handler_args=dict(default_filename="index.html"),或添加default_filename 作为StaticFileHandler 的初始化参数。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-27
        • 1970-01-01
        • 2012-02-01
        • 2013-11-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多