2013-01-17 10 views
14


Voglio sapere se c'è un modo migliore per gestire il mio file index.html con Tornado.
c'è un modo migliore per gestire index.html con Tornado?

Io uso StaticFileHandler per tutte le richieste e uso un MainHandler specifico per gestire la mia richiesta principale. Se io uso solo StaticFileHandler ho ottenuto un 403: errore di Forbidden

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

qui come faccio ora:

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() 
+1

Sarebbe meglio sostituire 'r"/"' e 'r" /(.*) "' con 'r"/$ "' e 'r" /(.*)$ "'. – akaRem

risposta

19

Si scopre che StaticFileHandler di Tornado include già la funzionalità nome file predefinito.

caratteristica è stata aggiunta nel Tornado versione 1.2.0: https://github.com/tornadoweb/tornado/commit/638a151d96d681d3bdd6ba5ce5dcf2bd1447959c

Per specificare un nome di file di default è necessario impostare il parametro "default_filename" come parte dell'inizializzazione WebStaticFileHandler.

Aggiornamento esempio:

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() 

Questo gestisce le richieste di root:

  • / ->/index.html

sub-directory richieste:

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

e sembra gestire correttamente i reindirizzamenti per le directory, che è bello:

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

Posso usare i tag di template con questi file .html? –

+0

Mi ci sono voluti circa 5 ore per trovare davvero questa incredibile risposta, mille grazie! – windsound

4

Non c'è bisogno di aggiungere in modo esplicito un StaticFileHandler; basta specificare il static_path e servirà quelle pagine.

È corretto che sia necessario un MainHandler, poiché per qualche motivo Tornado non servirà il file index.html, anche se si aggiunge il nome file all'URL.

In questo caso, questa piccola modifica al codice dovrebbe funzionare per voi:

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() 
+0

Non riesco a pubblicare file * .html nella mia cartella principale con questa soluzione. Ho bisogno di un gestore anche per questi file. –

+0

Quale versione di Tornado stai usando? Ho testato sia il tuo originale che la mia risposta, e ognuno può servire file * .html arbitrari. Sto usando Tornado 'version =" 2.4.post1 "', 'version_info = (2, 4, 0, 1)' (si trova in '__init __. Py'). –

+0

version = "2.4.1" version_info = (2, 4, 1, 0) Uso la stessa versione –

12

Grazie alla risposta precedente, ecco la soluzione che preferisco:

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() 

E Settings.py

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

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

le tue modifiche a 'index.html' possono essere viste solo aggiornando il browser e senza riavviare l'app? – Xuan

+0

@ xuan non capisco cosa vuoi che faccia? –

+0

scusa, dovrebbe essere più chiaro. Dì durante lo sviluppo della tua app, apporti le modifiche a 'index.html' e vuoi vedere le modifiche dal tuo browser. se 'index.html' è un modello renderizzato piuttosto che un file statico, puoi vedere le modifiche semplicemente aggiornando la pagina? – Xuan

5

Usa questo codice invece

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) 

ora utilizzare quella classe invece di StaticFileHandler vaniglia nell'applicazione ... lavoro fatto!

3

Ho cercato questo. Non utilizzare il rendering ha un sovraccarico aggiuntivo di modelli di analisi e fornisce errori sulle stringhe del tipo di modello in html statico. Ho trovato questo è il modo più semplice. Tornado sta cercando una parentesi di cattura in regex, basta dargli un gruppo di cattura vuoto.

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"}) 
]) 

Questo ha effetto di risolvere/a index.html e anche evitare risolve indesiderati come /views.html a static_dir/views.html

-1

Questo ha funzionato per me From the tornado docs:

Per pubblicare un file come index.html automaticamente quando viene richiesta una directory, impostare static_handler_args=dict(default_filename="index.html") nelle impostazioni dell'applicazione o aggiungere default_filename come argomento inizializzatore per StaticFileHandler.

Problemi correlati