@zhengyuhong
2016-04-08T01:41:48.000000Z
字数 5735
阅读 1576
posts
pip install --user tornado
more info about tornado en
more info about tornado zh
import sysimport tornado.ioloopimport tornado.webreload(sys)sys.setdefaultencoding('utf8')class MainHandler(tornado.web.RequestHandler):def get(self):self.write("hello world")if __name__ == '__main__':app = tornado.web.Application([("/", MainHandler)])app.listen(8080)tornado.ioloop.IOLoop.instance().start()
打开浏览器输入 http://localhost:8080/ 查看页面。
import sysimport tornado.ioloopimport tornado.webreload(sys)sys.setdefaultencoding('utf8')class MainHandler(tornado.web.RequestHandler):def get(self):self.write("You requestd the main page")class StoryHandler(tornado.web.RequestHandler):def get(self, story_id):self.write("You requested the story %s" % story_id)if __name__ == '__main__':app = tornado.web.Application([("/", MainHandler), ('/story/([0-9]+)', StoryHandler)])#URL 根目录 / 映射到 MainHandler,还将一个 URL 范式 /story/([0-9]+) 映射到 StoryHandler。正则表达式匹配的分组会作为参数引入的相应方法中:app.listen(8080)tornado.ioloop.IOLoop.instance().start()
打开浏览器输入 http://localhost:8080/ 查看页面。
class MainHandler(tornado.web.RequestHandler):def get(self):self.write('<html><body><form action="/" method="post">''<input type="text" name="message">''<input type="submit" value="Submit">''</form></body></html>')def post(self):self.set_header("Content-Type", "text/plain")self.write("You wrote " + self.get_argument("message"))
使用 get_argument() 方法来获取查询字符串参数,以及解析 GET/POST 的内容
请求处理程序可以通过 (HTTPRequest类)RequestHandler.request 访问到代表当前请求的对象。包含了一些有用的属性,包括:
arguments - 字典,所有的 GET 或 POST 的参数
files - 字典,所有通过 multipart/form-data POST 请求上传的文件
path - str,请求的路径( ? 之前的所有内容)
headers - tornado.httputil.HTTPHeaders,请求的开头信息
Tornado 中的重定向有两种主要方法,主要介绍RequestHandler.redirect
self.redirect
RedirectHandler。
你可以在使用 RequestHandler (例如 get)的方法中使用 self.redirect,将用户重定向到别的地方。例如当用户登录后重定向到用户个人主页。
import sysimport tornado.ioloopimport tornado.webreload(sys)sys.setdefaultencoding('utf8')class MainHandler(tornado.web.RequestHandler):def get(self):self.redirect('http://www.baidu.com')if __name__ == '__main__':app = tornado.web.Application([("/baidu", MainHandler)])app.listen(8080)tornado.ioloop.IOLoop.instance().start()
RequestHandler.redirect 通常会被用在自定义方法中get/post等,是由逻辑事件触发 的(例如环境变更、用户认证、以及表单提交)。而 RedirectHandler 是在每次匹配到请求 URL 时被触发。RedirectHandler会在你初始化 Application 时自动生成重定向地址。
class MainHandler(tornado.web.RequestHandler):def get(self):if not self.get_cookie("mycookie"):self.set_cookie("mycookie", "myvalue")self.write("Your cookie was not set yet!")else:self.write("Your cookie was set!")
Cookie 很容易被恶意的客户端伪造。加入你想在 cookie 中保存当前登陆用户的 id 之类的信息,你需要对 cookie 作签名以防止伪造。Tornado 通过 set_secure_cookie 和 get_secure_cookie 方法直接支持了这种功能。 要使用这些方法,你需要在创建应用时提供一个密钥,名字为 cookie_secret。 你可以把它作为一个关键词参数传入应用的设置中:
application = tornado.web.Application([(r"/", MainHandler),], cookie_secret="61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=")
签名过的 cookie 中包含了编码过的 cookie 值,另外还有一个时间戳和一个 HMAC 签名。如果 cookie 已经过期或者 签名不匹配,get_secure_cookie 将返回 None,这和没有设置 cookie 时的 返回值是一样的。上面例子的安全 cookie 版本如下:
class MainHandler(tornado.web.RequestHandler):def get(self):if not self.get_secure_cookie("mycookie"):self.set_secure_cookie("mycookie", "myvalue")self.write("Your cookie was not set yet!")else:self.write("Your cookie was set!")
当前已经认证的用户信息被保存在每一个请求处理器的 self.current_user 当中, 同时在模板的 current_user 中也是。默认情况下,current_user 为 None。
要在应用程序实现用户认证的功能,你需要复写请求处理中 get_current_user() 这 个方法,在其中判定当前用户的状态,比如通过 cookie。下面的例子让用户简单地使用一个 nickname 登陆应用,该登陆信息将被保存到 cookie 中
class BaseHandler(tornado.web.RequestHandler):def get_current_user(self):return self.get_cookie("user")class MainHandler(BaseHandler):def get(self):if not self.current_user:self.redirect("/login")returnname = tornado.escape.xhtml_escape(self.current_user)self.write("Hello, " + name)class LoginHandler(BaseHandler):def get(self):self.write('<html><body><form action="/login" method="post">''Name: <input type="text" name="name">''<input type="submit" value="Sign in">''</form></body></html>')def post(self):self.set_cookie("user", self.get_argument("name"))self.redirect("/")application = tornado.web.Application([(r"/", MainHandler),(r"/login", LoginHandler)])
对于那些必须要求用户登陆的操作,可以使用装饰器 tornado.web.authenticated。 如果一个方法套上了这个装饰器,但是当前用户并没有登陆的话,页面会被重定向到 login_url(应用配置中的一个选项),上面的例子可以被改写成:
class BaseHandler(tornado.web.RequestHandler):def get_current_user(self):return self.get_secure_cookie("user")class MainHandler(BaseHandler):@tornado.web.authenticateddef get(self):name = tornado.escape.xhtml_escape(self.current_user)self.write("Hello, " + name)class LoginHandler(BaseHandler):def get(self):self.write('<html><body><form action="/login" method="post">''Name: <input type="text" name="name">''<input type="submit" value="Sign in">''</form></body></html>')def post(self):self.set_secure_cookie("user", self.get_argument("name"))self.redirect("/")settings = {"cookie_secret": "61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=","login_url": "/login",}application = tornado.web.Application([(r"/", MainHandler),(r"/login", LoginHandler),], **settings)
通过在应用配置中指定 static_path 选项来提供静态文件服务:
settings = {"static_path": os.path.join(os.path.dirname(__file__), "static"),"login_url": "/login","template_path": os.path.join(os.path.dirname(__file__),"templates")}application = tornado.web.Application([(r"/", MainHandler),(r"/login", LoginHandler),(r"/(apple-touch-icon\.png)", tornado.web.StaticFileHandler, dict(path=settings['static_path'])),], **settings)
这样配置后,所有以 /static/ 开头的请求,都会直接访问到指定的静态文件目录, 比如 http://localhost:8888/static/foo.png 会从指定的静态文件目录中访问到 foo.png 这个文件。同时 /robots.txt 和 /favicon.ico 也是会自动作为静态文件处理(即使它们不是以 /static/ 开头)。
如你将 debug=True 传递给 Application 构造器,该 app 将以调试模式 运行。在调试模式下,模板将不会被缓存,而这个 app 会监视代码文件的修改, 如果发现修改动作,这个 app 就会被重新加载。在开发过程中,这会大大减少 手动重启服务的次数。然而有些问题(例如 import 时的语法错误)还是会让服务器 下线,目前的 debug 模式还无法避免这些情况。
调试模式和 HTTPServer 的多进程模式不兼容。在调试模式下,你必须将 HTTPServer.start 的参数设为不大于 1 的数字。
调试模式下的自动重载功能可以通过独立的模块 tornado.autoreload 调用, 作为测试运行器的一个可选项目,tornado.testing.main 中也有用到它。