Tornado 和如今的主流 Web 服務器框架(包括大多數 Python 的框架)有着明顯的區別:它是非阻塞式服務器,並且速度至關快。得利於其非阻塞的方式和對 epoll 的運用javascript
基本操做css
tornado_base.pyhtml
# Author:song import tornado.ioloop import tornado.web #配置信息 settings = { 'static_path':'static', 'static_url_prefix':'/song/',#別名 'template_path':'templates', } class MainHandler(tornado.web.RequestHandler): def get(self): self.write("Hello, world") #返回數據 class LoginHandler(tornado.web.RequestHandler): def get(self): #self.get_argument('p') 獲取請求參數,至關於django的request.GET.get('p') #self.get_body_argument('name') 獲取post內容信息 #self.set_cookie('k1','v1')設置cookie #self.set_header('h1','v1')設置請求頭 self.render("login.html",**{'k1':'song','k2':'shi','k3':[1,2,3,4],'k4':{'name':'a','age':18}}) #返回模板 def post(self, *args, **kwargs): print(self.get_argument('user')) self.redirect('https://home.cnblogs.com/u/master-song/')#重定向 #路由規則 application = tornado.web.Application([ (r"/index", MainHandler), (r"/login", LoginHandler), ],**settings) if __name__ == "__main__": #建立socket對象,將其加入select application.listen(8888) #開始循環監聽 tornado.ioloop.IOLoop.instance().start()
模板login.html前端
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <link rel="stylesheet" href="/song/comment.css"/> <title>Title</title> </head> <body> <h1>login</h1> {{k1}} {{k2}} <h1>列表</h1> <ul> {% for i in k3 %} <li>{{i}}</li> {% end %} </ul> <h1>字典</h1> {{k4}}<br> {{k4['name']}}<br> {{k4.get('name')}} <ul> {% for k,v in k4.items() %} <li>{{k}}:{{v}}</li> {% end %} <form method="post" action="login"> <input type="text" name="user"/> <input type="submit" value="提交"/> </ul> </body> </html>
comment.css 只寫了一句java
body{
background-color: blue;
}
login.html渲染圖web
Tornado默認提供的 UIMethod 和 UIModule,實現相似於Django的simple_tag的功能。redis
建立兩個py文件django
# Author:song def test1(self): return '測試前端使用函數'
# Author:song from tornado.web import UIModule from tornado import escape class test2(UIModule): def embedded_css(self): return 'body{color:blue}' #網頁引入<style type="text/css">body{color:blue}</style> def css_files(self): return 'a.css'# 引入<link href="/song/a.css" type="text/css" rel="stylesheet"> def javascript_files(self): return 'sk.js' #<script src="/song/sk.js" type="text/javascript"></script> def render(self, *args, **kwargs): print(args)#獲取內容(123) print(kwargs)#{} # return escape.xhtml_escape('<h1>測試代碼段前端渲染</h1>') #原樣顯示 <h1>測試代碼段前端渲染</h1> return '<h1>測試代碼段前端渲染</h1>' #加載效果後顯示
在tornado_base.py中服務器
import uimethods as mt
import uimodules as md
settings = {
'static_path':'static',
'static_url_prefix':'/song/',
'template_path':'templates',
'ui_methods':mt,
'ui_modules':md, #加上這兩行
}
web組件的定製cookie
1.session實現機制
# Author:song import uuid #基於內存的寫法 class Session(object): container = {} def __init__(self,handler): # 獲取用戶cookie,若是有,不操做,不然,給用戶生成隨即字符串 # - 寫給用戶 # - 保存在session nid = handler.get_cookie('session_id') if nid: if nid in Session.container: pass else: nid = str(uuid.uuid4()) Session.container[nid] = {} else: nid = str(uuid.uuid4()) Session.container[nid] = {} handler.set_cookie('session_id', nid, max_age=1000)#設置cookie並設超時時間 # nid當前訪問用戶的隨即字符串 self.nid = nid # 封裝了全部用戶請求信息 self.handler = handler def __setitem__(self, key, value): Session.container[self.nid][key] =value def __getitem__(self, item): return Session.container[self.nid].get(item) def __delitem__(self, key): del Session.container[self.nid][key] #基於redis class RedisSession(object): def __init__(self,handler): # 獲取用戶cookie,若是有,不操做,不然,給用戶生成隨即字符串 # - 寫給用戶 # - 保存在session nid = handler.get_cookie('session_id') if nid: if nid in Session.container: pass else: nid = str(uuid.uuid4()) # Session.container[nid] = {} # 鏈接redis寫值 # redis 服務器IP,端口(6379) # 根據Nid是字符串 => 6871237123 # 6871237123 % 3 = 0,1,2 # ['10.1.11.2','10.1.11.3','10.1.11.4'] else: nid = str(uuid.uuid4()) # Session.container[nid] = {} # 鏈接redis寫值 handler.set_cookie('session_id', nid, max_age=1000) # nid當前訪問用戶的隨即字符串 self.nid = nid # 封裝了全部用戶請求信息 self.handler = handler def __setitem__(self, key, value): #Session.container[self.nid][key] =value pass def __getitem__(self, item): #return Session.container[self.nid].get(item) pass def __delitem__(self, key): # del Session.container[self.nid][key] pass
# Author:song # session_module = "RedisSession" # 只容許兩種Session,RedisSession session_module = "Session"
# Author:song # Author:song import tornado.ioloop import tornado.web from tornado_session import session_key #配置信息 settings = { 'static_path':'static', 'static_url_prefix':'/song/', 'template_path':'templates', } class BaseHandler(object): def initialize(self): # 獲取用戶cookie,若是有,不操做,不然,給用戶生成隨即字符串 # - 寫給用戶 # - 保存在session from tornado_session import session session_module = getattr(session, session_key.session_module)#反向解析 self.session = session_module(self) super(BaseHandler,self).initialize() class IndexHandler(BaseHandler, tornado.web.RequestHandler): def get(self): if self.session['is_login']: self.write("Hello, world") else: self.redirect('/login') class LoginHandler(BaseHandler,tornado.web.RequestHandler): def get(self, *args, **kwargs): self.render('login.html') def post(self, *args, **kwargs): v = self.get_argument('user') if v == 'song': self.session['is_login'] = True self.redirect('/index') else: self.redirect('/login') application = tornado.web.Application([ (r"/index",IndexHandler ), (r"/login", LoginHandler), ],**settings) if __name__ == "__main__": application.listen(8888) tornado.ioloop.IOLoop.instance().start()
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>tornado-session</title> </head> <body> <form method="post" action="login"> <input type="text" name="user"/> <input type="submit" value="提交"/> </form> </body> </html>
若是選擇使用redis,可能須要用到分佈式
form簡單表單驗證
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>tornado_form</title> </head> <body> <form method="post" action="login"> <!--<input type="text" name="user"/>--> <!--<input type="email" name="email"/>--> {% raw obj.user %} {% raw obj.email %} <input type="submit" value="提交"/> </form> </body> </html>
# Author:song import tornado.web import re settings = { 'static_path': 'static', 'static_url_prefix': '/song/', 'template_path':'templates', } class StringField: def __init__(self,name): self.rex = "^\w+$" self.name = name self.value = '' self.error = "" def __str__(self): return "<input type='text' name='%s' value='%s' />" %(self.name,self.value,) class EmailField: def __init__(self,name): self.rex = "^\w+@.*$" self.name = name self.value = '' self.error = "" def __str__(self): return "<input type='text' name='%s' value='%s' />" %(self.name,self.value,) class LoginForm: def __init__(self): self.user = StringField(name='user') self.email = EmailField(name='email') def is_valid(self,handler): value_dict = {} flag = True for k,v in self.__dict__.items(): inp = handler.get_argument(k) rex = re.match(v.rex,inp) v.value = inp if rex: value_dict[k] = inp else: v.error = '%s 錯誤了..' %k flag = False return flag,value_dict class LoginHandler(tornado.web.RequestHandler): def get(self, *args, **kwargs): obj = LoginForm() self.render('login.html',**{'obj': obj}) def post(self, *args, **kwargs): obj = LoginForm() valid,value_dict = obj.is_valid(self) print(valid,value_dict) if valid: print(value_dict) self.write('welcome') else: return self.render('login.html',**{'obj': obj}) application = tornado.web.Application([ (r"/login", LoginHandler), ],**settings) if __name__ == "__main__": application.listen(8888) tornado.ioloop.IOLoop.instance().start()