Search code examples
pythonweb-applicationstornado

Understanding Information Flow in Tornado App


I'm teaching myself Tornado, so I bought a copy of Introduction to Tornado, and started working through the examples. I'm onto the third one, and it works, but I don't understand how/why.

Below is a modified, but functionally equivalent, version of the code in the book. I have a file called poemaker.py

import os.path
import tornado.web
from tornado.options import define, options


define("port", default=8000, help="run on the given port", type=int)


class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        self.render('index.html')


class PoemPageHandler(tornado.web.RequestHandler):
    def post(self):
        name = self.get_argument('name')
        noun1 = self.get_argument('noun1')
        noun2 = self.get_argument('noun2')
        verb = self.get_argument('verb')
        self.render('poem.html', mary=name, lamb=noun1, snow=noun2,
                    go=verb)


if __name__ == '__main__':
    import tornado.httpserver
    import tornado.ioloop
    import tornado.options

    tornado.options.parse_command_line()
    app = tornado.web.Application(
    handlers=[(r'/', IndexHandler), (r'/poem', PoemPageHandler)],
    template_path=os.path.join(os.path.dirname(__file__), "templates")
    )

    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()

Then in the same directory I have another directory called templates which has two html files: index.html and poem.hmtl.

index.html:

<!DOCTYPE html>
    <html>
    <head><title>Poem Maker Pro</title></head>
    <body>
        <h1>Enter terms below.</h1>
        <form method="post" action="/poem">
            <p>Name<br><input type="text" name="name"></p>
            <p>Singular noun<br><input type="text" name="noun1"></p>
            <p>Singualr noun<br><input type="text" name="noun2"></p>
            <p>Verb w/o object<br><input type="text" name="verb"></p>
            <input type="submit">
    </form>
    </body>
</html>

When I start the server, and go to http://localhost:8000/, I see the contents of index.html rendered. Which is exactly what I would expect, because that's what IndexHandler should be doing.

When I fill in the form, and hit submit, I get taken to http://localhost:8000/poem which has my poem. So the app works.

What I don't understand is the step in the middle. What's going when I hit submit? How does the application know that submitting the form should me to http://localhost:8000/poem?


Solution

  • Basically, on your example you have setup a RESTful service using tornado.

    On the HTML form you have specify, with method="post", that on submitting the form you will send the data in the fields as HTTP post request. Also by using action="/poem" you specify where to send the form-data when a form is submitted.

    When you hit submit,you sends a HTTP post request to your tornado web server. When your Tornado server receives the request, Tornado iterates over the handlers list and creates an instance of the tornado.web.RequestHandler subclass, PoemPageHandler, which is associated with the regular expression "/poem" which defined in the form as action, and then calls the post() method.

    The last command of the post() method is render: self.render('poem.html', mary=name, lamb=noun1, snow=noun2, go=verb) which renders the template poem.html with the parameters passed and redirect you to http://localhost:8000/poem.