First, why Choose Tornado:
1. High-performance network library, which can be done with gevent,twisted,libevent and so on.
Provides asynchronous IO support, timeout event handling, based on which tcpserver,httpclient, especially curlhttpclient,
Must be first in the existing HTTP client. Can be used as a crawler, game server, as far as I know the industry has used tornado as a game server
2.web frame, which can and django,flask pair.
Provides web framework prerequisites such as routing, templates, and more. And the other difference is that Tornado is asynchronous and naturally suitable for long rotation,
This is also friendfeed invention Tornado reason, the current flask also can support, but must rely on gevent and so on
3. A more complete HTTP server, this can be compared with Nginx,apache,
But only supports http1.0, so using Nginx to do the front paragraph is not only to make better use of multi-core, but also to allow it to support http1.1
4. Complete WSGI server, which can be compared with gunicore,gevent WSGI server,
That is to say, you can let flask run on tornado, let tornado accelerate flask
5. Provide a complete websocket support, which makes HTML5 games, etc. to facilitate.
Like the long rotation is the use of websocket, but WebSocket phone support is not very good,
Some time ago had to use timed Ajax to send a large number of requests, look forward to the mobile browser quickly catching up
Use Tornado to create a simple book introduction page
Okay, now, let's take a look at the code implementation of the book introduction page:
1. Create an entry file for a Web service blockmain.py
#coding: utf-8
import tornado.web
import tornado.httpserver
import tornado.ioloop
import tornado.options
import os.path
import json
import urllib2
from tornado.options import define, options
define ("port", default = 8000, help = "run on the given port", type = int)
class MainHandler (tornado.web.RequestHandler):
def get (self):
self.render (
"index.html",
page_title = "Burt's Books ¦ Home",
header_text = "Welcome to Burt's Books!",
books = ['Detailed php', 'python', 'PHP', 'Little Times']
)
class HelloModule (tornado.web.UIModule):
def render (self):
return '<h1> I am yyx and this is an information from module hello! </ h1>'
class BookModule (tornado.web.UIModule):
def render (self, bookname):
doubanapi = r'https: //api.douban.com/v2/book/ '
searchapi = r'https: //api.douban.com/v2/book/search? q = '
searchurl = searchapi + bookname
searchresult = urllib2.urlopen (searchurl) .read ()
bookid = json.loads (searchresult) ['books'] [0] ['id']
bookurl = doubanapi + bookid
injson = urllib2.urlopen (bookurl) .read ()
bookinfo = json.loads (injson)
return self.render_string ('modules / book.html', book = bookinfo)
def embedded_javascript (self):
return "document.write (\" hi! \ ")"
def embedded_css (self):
return '' '.book {background-color: # F5F5F5}
.book_body {color: red}
'' '
def html_body (self):
return '<script> document.write ("Hello!") </ script>'
if __name__ == "__main__":
tornado.options.parse_command_line ()
app = tornado.web.Application (
handlers = [
(r '/', MainHandler),
],
template_path = os.path.join (os.path.dirname (__ file __), 'templates'),
static_path = os.path.join (os.path.dirname (__ file __), 'static'),
debug = True,
ui_modules = {'Hello': HelloModule, 'Book': BookModule}
)
http_server = tornado.httpserver.HTTPServer (app)
http_server.listen (options.port)
tornado.ioloop.IOLoop.instance (). start ()
To illustrate, some basic MVC concepts:
Tornado also uses pathinfo mode to match the user's input to obtain parameters, and then calls the corresponding processing function. It is processed by setting the corresponding class class for each matching mode. For example, I use the class MainHandler to process from / Get request
MainHandler renders the request render to index.html, the parameter is called by {{parameter}} in index.html
2. Establish the corresponding template, first create a basic parent class main.html template, create the templates directory, create main.html under it, this template just defines the most basic web page framework, and the specific content inside is inherited from it Subclasses to achieve
<html>
<head>
<title> {{page_title}} </ title>
<link rel = "stylesheet" href = "{{static_url (" css / style.css ")}}" />
</ head>
<body>
<div id = "container">
<header>
{% block header%} <h1> Burt's Books </ h1> {% end%}
</ header>
<div id = "main">
<div id = "content">
{% block body%} {% end%}
</ div>
</ div>
<footer>
{% set mailLink = '<a href="mailto:contact@burtsbooks.com"> Contact Us </a>'%}
{% set script = '<script> alert ("hello") </ script>'%}
{% block footer%}
<p>
For more information about our selection, hours or events, please email us at {% raw mailLink%}
<!-{% raw script%} will be output here as it is, that is, a box will be popped up->
</ p>
{% end%}
</ footer>
</ div>
<script src = "{{static_url (" js / script.js ")}}"> </ script>
</ body>
</ html>
Here is the definition of a main frame, where the {% block header%} <h1> Burt's Books </ h1> {% end%} is the inherited block for the subclass template. main.html, specifically what is written in this block is implemented by the subclass, if not, the default value of the parent class is used, such as <h1> Burt's Books </ h1> here, the MainHandler class is render to an index.html , Then write an index.html to inherit this parent class
{% extends "main.html"%}
{% block header%}
<h1> {{header_text}} </ h1>
{% end%}
{% block body%}
<div id = "hello">
<p> Welcome to Burt's Books! </ p>
{% module Hello ()%}
{% for book in books%}
{% module Book (book)%}
{% end%}
<p> ... </ p>
</ div>
{% end%}
Simple and concise, this is also the advantage of using inheritance, there is no need to repeat the parent class, as long as the block content of the parent class can be achieved
Parameters in the render method in the MainHandler class
page_title = "Burt's Books | Home",
header_text = "Welcome to Burt's Books!",
books = ['Detailed php', 'python', 'PHP', 'Little Times']
Will be sent here via parameters
The tornado template can use python code, plus {%%} when using if for while, etc., use {% end%} at the end
The code {% module Book (book)%} will call the module defined in the entry service file and the module corresponding to 'Book'
ui_modules = {'Hello': HelloModule, 'Book': BookModule} which is BookModule, see the definition of BookModule above
class BookModule (tornado.web.UIModule):
def render (self, bookname):
doubanapi = r'https: //api.douban.com/v2/book/ '
searchapi = r'https: //api.douban.com/v2/book/search? q = '
searchurl = searchapi + bookname
searchresult = urllib2.urlopen (searchurl) .read ()
bookid = json.loads (searchresult) ['books'] [0] ['id']
bookurl = doubanapi + bookid
injson = urllib2.urlopen (bookurl) .read ()
bookinfo = json.loads (injson)
return self.render_string ('modules / book.html', book = bookinfo)
BookModule inherits from tornado.web.UIModule. The use of UI module is the last render_string () method to render an object into a template. Here I simply use Douban's book api. First search through search to include keywords Book information, return the id of the first book, and then use the book api to query the specific information of the book, and render the information of the specific book to the corresponding template
Create the modules directory under the templates directory, and then create a book.html, here is the content frame of the specific book to display
<div class = "book">
<h3 class = "book_title"> {{book ["title"]}} </ h3>
<a href="{{book['alt']}}" target="_blank"> <p> Click for details </ p> </a>
{% if book ["subtitle"]! = ""%}
<h4 class = "book_subtitle"> {{book ["subtitle"]}} </ h4>
{% end%}
<img src = "{{book [" images "] [" large "]}}" class = "book_image" />
<div class= "book_details">
<div class = "book_date_released"> Released: {{book ["pubdate"]}} </ div>
<h5> Description: </ h5>
<div class = "book_body"> {% raw book ["summary"]%} </ div>
</ div>
</ div>
The final file directory structure should be like this
├── blockmain.py
└── templates
├── index.html
├── main.html
└── modules
└── book.html
The execution of the program is this:
First use the MainHandler class to access index.html ----> index.html from the path '/' inherited from main.html ----> index.html {% module Book (book)%} in turn find blockmain The ui_modules corresponding to the Book in .py ----> ui_modules will render the content of the book object obtained by the query to the book.html under the modules, so that the complete content is presented, without doing the front end ... through python blockmain .py start the service, access to the following web page through http: // localhost: 8000