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
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# 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= "127.0.0.1:3306", 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},
Xsrf_cookies=true,
cookie_secret= "__todo:_generate_your_own_random_value _here__ ",
Login_url="/auth/login ",
Debug=true,
)
#然后调用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
@property
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"
"DESC LIMIT 5")
If not entries:
#redirect Redirect to a URL
Self.redirect ("/compose")
Return
#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"
"DESC")
Self.render ("archive.html", entries=entries)
Class Feedhandler (Basehandler):
def get (self):
Entries = Self.db.query ("SELECT * from Entries ORDER by published"
"DESC LIMIT 10")
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
#execute是执行的意思
Self.db.execute (
"UPDATE entries SET title =%s, Markdown =%s, html =%s"
"WHERE id =%s", title, text, HTML, int (ID))
Else
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 ()) ",
Self.current_user.id, 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))
return
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 "])
Else:
Self.redirect ("/")
return
Else:
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