Tornado的使用
Tornado 和现在的主流 Web 服务器框架(包括大多数 Python 的框架)有着明显的区别:它是非阻塞式服务器,而且速度相当快。得利于其非阻塞的方式和对 epoll 的运用
基本操作
tornado_base.py
# 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>
login.html
comment.css 只写了一句
body{
background-color: blue;
}
login.html渲染图
Tornado默认提供的 UIMethod 和 UIModule,实现类似于Django的simple_tag的功能。
创建两个py文件
# Author:song def test1(self):
return '测试前端使用函数'
uimethods
# 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>' #加载效果后显示
uimodules
在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组件的定制
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
session
# Author:song
# session_module = "RedisSession" # 只允许两种Session,RedisSession
session_module = "Session"
session_key
# 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()
tornado_session_test
<!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>
login.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>
login.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()
tornado_form
Tornado的使用的更多相关文章
- Python(九)Tornado web 框架
一.简介 Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本.这个 Web 框架看起来有些像web.py 或者 Google 的 webapp,不过 ...
- 使用tornado,我们可以做什么?
以下介绍都是建立在python2.x的基础上面,tornado使用任意版本皆可. 如果我们需要对外提供一个http server(web api)/websocket server时,我们都可以使用t ...
- tornado session
[转]tornado入门 - session cookie 和session 的区别: 1.cookie数据存放在客户的浏览器上,session数据放在服务器上. 2.cookie不是很安全,别人可以 ...
- tornado template
若果使用Tornado进行web开发可能会用到模板功能,页面继承,嵌套... 多页应用模板的处理多半依赖后端(SPA就可以动态加载局部视图),就算是RESTfull的API设计,也不妨碍同时提供部分模 ...
- tornado上手
http://www.tornadoweb.org/en/stable/ http://www.cnblogs.com/fanweibin/p/5418697.html import tornado. ...
- tornado+sqlalchemy+celery,数据库连接消耗在哪里
随着公司业务的发展,网站的日活数也逐渐增多,以前只需要考虑将所需要的功能实现就行了,当日活越来越大的时候,就需要考虑对服务器的资源使用消耗情况有一个清楚的认知. 最近老是发现数据库的连接数如果 ...
- centos 6.7 搭建tornado + nginx + supervisor的方法(已经实践)
首先,本来不想写这篇博客了,但是我测试了很多网上的例子包括简书的,全不行,我总结原因是自己太笨,搞了俩个晚上,后来决定,自己还是写一篇记录下来,保证自己以后使用 环境: centos6.7 64 py ...
- tornado中将cookie值设置为json字符串
不熟悉,找了很久,能FQ的话, https://groups.google.com/forum/#!topic/python-tornado/9Y--NgwjP_w 2楼有解释. tornado.es ...
- tornado 异步调用系统命令和非阻塞线程池
项目中异步调用 ping 和 nmap 实现对目标 ip 和所在网关的探测 Subprocess.STREAM 不用担心进程返回数据过大造成的死锁, Subprocess.PIPE 会有这个问题. i ...
- 离线安装 Python 2.7, paramiko 和 tornado
无非就是离线安装, 步骤比较繁琐, 记录一下. 需求很简单, 一个离线安装的 Python, 能跑 tornado 和 paramiko 1. 离线安装 Python 2.7 .tgz cd Pyth ...
随机推荐
- Android中StateListDrawable的种类(状态的种类)
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="ht ...
- Java实现凸包问题
1 问题描述 给定一个平面上n个点的集合,它的凸包就是包含所有这些点的最小凸多边形,求取满足此条件的所有点. 另外,形象生动的描述: (1)我们可以把这个问题看作如何用长度最短的栅栏把n头熟睡的老虎围 ...
- java实现第四届蓝桥杯阶乘位数
阶乘位数 题目描述 如图p1.jpg所示,3 x 3 的格子中填写了一些整数. 我们沿着图中的红色线剪开,得到两个部分,每个部分的数字和都是60. 本题的要求就是请你编程判定:对给定的m x n 的格 ...
- java实现第五届蓝桥杯等额本金
等额本金 题目描述 小明从银行贷款3万元.约定分24个月,以等额本金方式还款. 这种还款方式就是把贷款额度等分到24个月.每个月除了要还固定的本金外,还要还贷款余额在一个月中产生的利息. 假设月利率是 ...
- iOS - 多线程——GCD
什么是GCD Grand Central Dispatch(强大的调度器),是一个C语言API: 作用:多核并行运算的解决方案: GCD中有2个核心概念 ...
- MIPI CSI-2
目录 1 MIPI简介 2 MIPI CSI-2简介 2.1 MIPI CSI-2 的层次结构 2.2 CSI-2协议层 2.3 打包/解包层 2.4 LLP(Low Level Protocol)层 ...
- Vue路由-详细总结
Vue路由vue-router 前面的话 在Web开发中,路由是指根据URL分配到对应的处理程序.对于大多数单页面应用,都推荐使用官方支持的vue-router.Vue-router通过管理URL ...
- Java I/O模型及其底层原理
Java I/O是Java基础之一,在面试中也比较常见,在这里我们尝试通过这篇文章阐述Java I/O的基础概念,帮助大家更好的理解Java I/O. 在刚开始学习Java I/O时,我很迷惑,因为网 ...
- Spyder汉化教程
汉化包下载地址:https://www.lizenghai.com/archives/523.html 1.解压汉化包 2. 3.1.运行汉化补丁PS C:\WINDOWS\system32> ...
- Flutter 中由 BuildContext 引发的血案
今天和各位分享一个博主在实际开发中遇到的问题,以及解决方法.废话不多说,我们先来看需求: 我们要做一个iOS风格的底部菜单弹出组件,具体涉及showCupertinoModalPopup()方法,该方 ...