您的位置:首页 > 其它

Tornado基本应用

2018-03-10 18:38 197 查看

Tornado简介

Tornado有自己的socket(异步非阻塞,原生支持WebSocket),Django没有。

Tornado的模板语言更接近Python风格,比Django要好理解。

Demo示例

from tornado import ioloop
from tornado.web import RequestHandler,Application

class IndexHandler(RequestHandler):
def get(self):
self.write("Hello, world")

application = Application([
(r"/index", IndexHandler),
])

if __name__ == "__main__":
application.listen(8888)
ioloop.IOLoop.instance().start()


  

Tornado路由系统以及通过别名反向生成url

from tornado import ioloop
from tornado.web import RequestHandler,Application

class IndexHandler(RequestHandler):
def get(self):
url1 = self.application.reverse_url('alias_name1')
url2 = self.application.reverse_url('alias_name2',666)
print(url1)
print(url2)
self.write("Hello, world")

class HomeHandler(RequestHandler):
def get(self,uid):
print(uid)
self.write("Hello, Home")

application = Application([
(r"/index", IndexHandler,{},'alias_name1'),
(r"/home/(\d+)", HomeHandler,{},'alias_name2'),
])

# 支持通过域名进行匹配,域名匹配到然后再匹配 url
# application.add_handlers("blog.standby.pub",[
#     (r"/index", IndexHandler),
#     (r"/home/(\d+)", HomeHandler),
# ])

if __name__ == "__main__":
application.listen(80)
ioloop.IOLoop.instance().start()


  

种子管理系统

  路由系统

  多种方式实现登录验证

  cookie

  xsrf

  UImethod 和 UImodule

  模板引擎

  

目录结构

tree /f

│  app.py
│  my_uimethod.py
│  my_uimodule.py
│
├─controllers
│     account.py
│     seed.py
│     __init__.py
│
│
├─statics
│      commons.css
│      footer.css
│
├─tpl
footer.html
layout.html
login.html
seed.html
video.html


  

app.py

from controllers.account import *
from controllers.seed import *
import my_uimethod
import my_uimodule

settings = {
'template_path':'tpl',
'static_path':'statics',
'static_url_prefix':'/static/',
'xsrf_cookies': True, # csrf配置
'cookie_secret':'asahcaoclacnqwncakcnal',
'login_url':'/login.html',
'ui_methods':my_uimethod,
'ui_modules':my_uimodule,
}

application = Application([
(r"/login.html", LoginHandler,{},'login'),
(r"/logout.html", LogoutHandler,{},'logout'),
(r"/seed.html", SeedHandler,{},'seed'),
(r"/video.html", VideoHandler,{},'video'),
],**settings)

if __name__ == "__main__":
application.listen(80)
ioloop.IOLoop.instance().start()


  

account.py

from tornado import ioloop
from tornado.web import RequestHandler,Application

class LoginHandler(RequestHandler):
def get(self,*args, **kwargs):
self.render('login.html',msg="")

def post(self, *args, **kwargs):
"""
self.request 包含了所有数据:
HTTPServerRequest(protocol='http',
host='127.0.0.1',
method='POST',
uri='/login.html?next=%2Fseed.html',
version='HTTP/1.1',
remote_ip='127.0.0.1',
headers={
'Content-Type': 'application/x-www-form-urlencoded',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36',
'Cache-Control': 'max-age=0',
'Host': '127.0.0.1',
'Accept-Encoding': 'gzip, deflate, br',
'Origin': 'http://127.0.0.1',
'Content-Length': '87',
'Referer': 'http://127.0.0.1/login.html?next=%2Fseed.html',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'Cookie': 'session=eyJ1c2VyX2luZm8iOiJhbGV4In0.DYUE4A.AhS8WvwJlQa8ium1YnF6tgJHwn0; _xsrf=2|50188c8e|5f181ad48a05219cb3bcf8117255223f|1520676667'
})
"""

name = self.get_argument('name')    # 去GET和POST里取值
pwd = self.get_argument('pwd')
args = self.get_arguments('name')   # 类似Django里的 getlist()
# self.get_query_argument()   # 去GET里取值
# self.get_query_arguments()  # 类似Django里的 getlist()
# self.get_body_argument()    # 去POST里取值
# self.get_body_arguments()   # # 类似Django里的 getlist()

if 'alex' == name and '123' == pwd:
import time
deadline = time.time() + 3600
# self.set_cookie('user_info',name,expires=deadline)  # 普通的cookie
self.set_secure_cookie('user_info',name,expires=deadline) # 加盐/签名的cookie,需要在settings里配置cookie_secret

# self.redirect('/seed.html')
# url = self.reverse_url('seed')
# self.redirect(url)

# 如果使用authenticated来装饰login的get方法,并且在验证发现用户没有登录的情况下
# 则在跳转到登录页面,并会自动带上一个next字段到get请求里:http://127.0.0.1/login.html?next=%2Fseed.html
next_url = self.get_query_argument('next','')
if not next_url:
next_url = self.reverse_url('seed')
self.redirect(next_url)
else:
self.render('login.html',msg="用户名或密码错误")

class LogoutHandler(RequestHandler):
def get(self,*args, **kwargs):
self.write("Bye...")
def post(self, *args, **kwargs):
pass


  

seed.py

from tornado import ioloop
from tornado.web import RequestHandler,Application
from tornado.web import authenticated

# 手写实现登录验证
# class SeedHandler(RequestHandler):
#     def get(self,*args, **kwargs):
#         # name = self.get_cookie('user_info')
#         name = self.get_secure_cookie('user_info')
#         if not name:
#             self.redirect('/login.html')
#             return
#         self.write("Seed!")

""" 单继承
class ParentHandler(RequestHandler):
# 这个方法是tornado给预留的,如果要使用 tornado.web.authenticated 来登录验证就必须自己重写这个方法
def get_current_user(self):
return self.get_secure_cookie('user_info')

# 使用装饰器实现登录验证
class SeedHandler(ParentHandler):

@authenticated
def get(self,*args, **kwargs):
seed_list = [
{'title':'小麦','price':20},
{'title':'水稻','price':50},
{'title':'玉米','price':30}
]
self.render('seed.html',seed_list=seed_list)

class VideoHandler(ParentHandler):

@authenticated
def get(self, *args, **kwargs):
video_list = [
{'title': '柯南', 'price': 220},
{'title': '一人之下', 'price': 90},
{'title': '虫师', 'price': 40}
]
self.render('video.html', video_list=video_list)

"""

""" 多继承 """
class ParentHandler(object):
# 这个方法是tornado给预留的,如果要使用 tornado.web.authenticated 来登录验证就必须自己重写这个方法
def get_current_user(self):
return self.get_secure_cookie('user_info')

# 使用装饰器实现登录验证
class SeedHandler(ParentHandler,RequestHandler):

@authenticated
def get(self,*args, **kwargs):
seed_list = [
{'title':'小麦','price':20},
{'title':'水稻','price':50},
{'title':'玉米','price':30}
]
self.render('seed.html',seed_list=seed_list)

class VideoHandler(ParentHandler,RequestHandler):

@authenticated
def get(self, *args, **kwargs):
video_list = [
{'title': '柯南', 'price': 220},
{'title': '一人之下', 'price': 90},
{'title': '虫师', 'price': 40}
]
self.render('video.html', video_list=video_list)


  

自定义UIMethod以UIModule

def tab(self):
"""
在html页面里的调用方式:
{{ tab() }}
{% raw tab() %}
"""
# print(self)  # <controllers.seed.VideoHandler object at 0x000000000360D6A0>
# return 'UIMethod'
return "<a href='http://www.baidu.com'>百度</a>"

def sum(self, num1, num2):
return num1+num2


  

from tornado.web import UIModule
from tornado import escape

class Custom(UIModule):
def render(self, *args, **kwargs):
print(self,args,kwargs)
return "UIModule 不仅可以返回内容还可以引入/嵌入 css和js,可以用来做一个自定制的组合模块,比如分页,只需要在使用的时候引入下就可以。"

# 引入css
def css_files(self):
return ["/static/footer.css",]

# 嵌入css
def embedded_css(self):
tpm = """
.foot{
height: 80px;
}
"""
return tpm

# 引入js
def javascript_files(self):
return ["/static/common.js",]

# 嵌入js
def embedded_javascript(self):
tpm ="""
v = 123;
console.log(v);
"""
return tpm


  

seed.html

{% extends layout.html %}

{% block content %}

<h1>种子列表</h1>

{% module Custom(123) %}

<ul>
{% for item in seed_list %}
<li> {{ item['title'] }} - {{ item['price'] }}</li>
<li> {{ item.get('title','') }} - {{ item.get('price','') }}</li>
{% end %}
</ul>

{% include 'footer.html' %}
{% end %}


  

video.html

{% extends layout.html %}

{% block content %}

<h1>视频列表 {{ sum(1,3) }}</h1>
{{ tab() }}
{% raw tab() %}
<ul>
{% for item in video_list %}
<li> {{ item['title'] }} - {{ item['price'] }}</li>
<li> {{ item.get('title','') }} - {{ item.get('price','') }}</li>
{% end %}
</ul>

{% end %}


  

login.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--<link rel="stylesheet" href="/static/commons.css">-->
<link rel="stylesheet" href="{{ static_url('commons.css') }}">
</head>
<body>

<h1 class="c1">Login</h1>
<form action="" method="post">
{% raw xsrf_form_html() %}
<input type="text" name="name">
<input type="text" name="pwd">
<input type="submit" value="提交"> {{ msg }}
</form>

</body>
</html>


  

更多请参考:http://www.cnblogs.com/wupeiqi/articles/5702910.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: