Analysis and use of Tornado frame blog module

Source: Internet
Author: User
The code is as follows:

#!/usr/bin/env python
# Copyright Facebook
# Licensed under the Apache License, Version 2.0 (the "License"); May
# not use this file except in compliance with the License. Obtain
# A copy of the License at
# unless required by applicable or agreed to writing, software
# Distributed under the License is distributed on a "as is" BASIS, without
# warranties or CONDITIONS of any KIND, either express OR implied. See the
# License for the specific language governing permissions and limitations
# under the License.

Import Markdown
Import Os.path
Import re
Import Torndb
Import Tornado.auth
Import Tornado.httpserver
Import Tornado.ioloop
Import Tornado.options
Import Tornado.web
Import Unicodedata

From tornado.options Import define, Options
#定义一些通用的配置信息, such as database connection information, port information
define ("Port", default=8888, help= "Run on the given port", Type=int)
define ("Mysql_host", default= "", help= "blog Database Host")
Define ("Mysql_database", default= "blog", help= "blog database name")
Define ("Mysql_user", default= "root", help= " Blog database user ")
Define (" Mysql_password ", default=" sa123 ", help=" blog Database Password ")

#定义Application信息, which is the
Class application (Tornado.web.Application) that inherits Tornado.web.Application:
# __init__ The function automatically calls
Def __init__ (self):
#这里就是url对应的控制器, corresponding to a class below, to handle the logic inside
handlers = [
(r "/", Homehandler),
(r "/ Archive ", Archivehandler),
(R"/feed ", Feedhandler),
(R"/entry/([^/]+) ", Entryhandler),
(R"/compose ", Composehandler),
(R "/auth/login", Authloginhandler),
(R "/auth/logout", Authlogouthandler),
#设置, such as blog title, template directory, static file directory, XSRF, whether to debug
Settings = Dict (
blog_title=u "Tornado blog",
Template_path=os.path.join ( Os.path.dirname (__file__), "Templates"),
Static_path=os.path.join (Os.path.dirname (__file__), "Static"),
UI _modules={"Entry": Entrymodule},
cookie_secret= "__todo:_generate_your_own_random_value _here__ ",
Login_url="/auth/login ",
#然后调用tornado The web.application function of the __init__ class is loaded in.
Tornado.web.application.__init__ (self, handlers, **settings)

# One global connection to the blog DB across all handlers
Self.db = torndb. Connection (
Host=options.mysql_host, Database=options.mysql_database,
User=options.mysql_user, Password=options.mysql_password)

#基类, inherited from Tornado.web.RequestHandler, the following classes are inherited from this class.
Class Basehandler (Tornado.web.RequestHandler):
#属性装饰器, make the DB function an attribute that is easy to use directly behind
def db (self):
Return self.application.db
def get_current_user (self):
user_id = Self.get_secure_cookie ("Blogdemo_user")
If not User_id:return None
Return Self.db.get ("select * FROM authors WHERE id =%s", int (user_id))

Class Homehandler (Basehandler):
def get (self):
#query Query Many columns
Entries = Self.db.query ("SELECT * from Entries ORDER by published"
If not entries:
#redirect Redirect to a URL
Self.redirect ("/compose")
#render render a template, followed by a parameter
Self.render ("home.html", entries=entries)

Class Entryhandler (Basehandler):
def get (self, slug):
#get Get a value
Entry = Self.db.get ("SELECT * from entries WHERE slug =%s", slug)
#raise triggers an error message that must be followed by the type
If not entry:raise tornado.web.HTTPError (404)
Self.render ("entry.html", Entry=entry)

Class Archivehandler (Basehandler):
def get (self):
Entries = Self.db.query ("SELECT * from Entries ORDER by published"
Self.render ("archive.html", entries=entries)

Class Feedhandler (Basehandler):
def get (self):
Entries = Self.db.query ("SELECT * from Entries ORDER by published"
Self.set_header ("Content-type", "Application/atom+xml")
Self.render ("Feed.xml", entries=entries)

Class Composehandler (Basehandler):
@tornado. web.authenticated
def get (self):
id = self.get_argument ("id", None)
Entry = None
If ID:
Entry = Self.db.get ("SELECT * from entries WHERE id =%s", int (ID))
Self.render ("compose.html", Entry=entry)

@tornado. web.authenticated
Def post (self):
id = self.get_argument ("id", None)
title = Self.get_argument ("title")
Text = self.get_argument ("Markdown")
html = markdown.markdown (text)
If ID:
Entry = Self.db.get ("SELECT * from entries WHERE id =%s", int (ID))
If not entry:raise tornado.web.HTTPError (404)
slug = Entry.slug
Self.db.execute (
"UPDATE entries SET title =%s, Markdown =%s, html =%s"
"WHERE id =%s", title, text, HTML, int (ID))
slug = Unicodedata.normalize ("NFKD", title). Encode (
"ASCII", "ignore")
slug = Re.sub (r "[^\w]+", "" ", Slug)
slug = "-". Join (Slug.lower (). Strip (). Split ())
If not Slug:slug = "entry"
While True:
E = Self.db.get ("SELECT * from entries WHERE slug =%s", slug)
If not e:break
Slug + = "-2"
Self.db.execute (
"INSERT into Entries (author_id,title,slug,markdown,html,"
Published) VALUES (%s,%s,%s,%s,%s,utc_timestamp ()) ",, title, slug, text, html)
Self.redirect ("/entry/" + slug)

Class Authloginhandler (Basehandler, tornado.auth.GoogleMixin):
@tornado. web.asynchronous
Def get ( Self):
If Self.get_argument ("Openid.mode", None):
Self.get_authenticated_user (Self.async_callback (self._on _auth))
Self.authenticate_redirect ()
#这里定义一个函数, for the above call
Def _on_auth (self, user):
If not User:
Raise Tornado.web.HTTPError ("Google auth failed")
Author = self.db.get ("select * FROM authors WHERE email = %s ",
user[" email "])
If not author:
# auto-create First author
Any_author = Self.db.get (" Select * FROM auth ORS LIMIT 1 ")
If not any_author:
author_id = Self.db.execute (
INSERT into authors (Email,name) VALUES (%s,%s) ",
user[" email "], user[" name "])
Self.redirect ("/")
author_id = author[" id "]< br> Self.set_secure_cookie ("Blogdemo_user", str (author_id))
Self.redirect (Self.get_argument ("Next", "/"))

Class Authlogouthandler (Basehandler):
def get (self):
Self.clear_cookie ("Blogdemo_user")
#get_argument为获得next参数的值, the default is "/"
Self.redirect (Self.get_argument ("Next", "/"))

Class Entrymodule (Tornado.web.UIModule):
def render (self, entry):
Return self.render_string ("modules/entry.html", Entry=entry)

def main ():
Tornado.options.parse_command_line ()
Http_server = Tornado.httpserver.HTTPServer (Application ())
Http_server.listen (Options.port)
Tornado.ioloop.IOLoop.instance (). Start ()

if __name__ = = "__main__":
Main ()

Finally, summarize:

1) Several demos provided in the Tornado framework create an application in this form
2) for each controller function, either, there can be only 2 external functions, one is get, one is post
3) database has 3 call mode, query,get,exec
4) Get the value of the parameter using the Get_argument function
5) redirect with redirect function
6) All functions are properties of this class, and all are called with self
7) render template with render function

  • Related Article

    Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.