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
?
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
.