一、快速上手

#!/usr/bin/env python
# -*- coding:utf-8 -*- import tornado.ioloop
import tornado.web class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world") application = tornado.web.Application([
(r"/index", MainHandler),
]) if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()

第一步:执行脚本,监听 8888 端口

第二步:浏览器客户端访问 /index  -->  http://127.0.0.1:8888/index

第三步:服务器接受请求,并交由对应的类处理该请求

第四步:类接受到请求之后,根据请求方式(post / get / delete ...)的不同调用并执行相应的方法

第五步:方法返回值的字符串内容发送浏览器

二、路由系统

路由系统其实就是 url 和 类 的对应关系,这里不同于其他框架,其他很多框架均是 url 对应 函数,Tornado中每个url对应的是一个类。

#!/usr/bin/env python
# -*- coding:utf-8 -*- import tornado.ioloop
import tornado.web class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world") class StoryHandler(tornado.web.RequestHandler):
def get(self, story_id):
self.write("You requested the story " + story_id) class BuyHandler(tornado.web.RequestHandler):
def get(self):
self.write("buy.wupeiqi.com/index") application = tornado.web.Application([
(r"/index", MainHandler),
(r"/story/([0-9]+)", StoryHandler),
]) application.add_handlers('buy.wupeiqi.com$', [
(r'/index',BuyHandler),
]) if __name__ == "__main__":
application.listen(80)
tornado.ioloop.IOLoop.instance().start()

三、模板

Tornao中的模板语言和django中类似,模板引擎将模板文件载入内存,然后将数据嵌入其中,最终获取到一个完整的字符串,再将字符串返回给请求者。

Tornado 的模板支持“控制语句”和“表达语句”,控制语句是使用 {% 和 %} 包起来的 例如 {% if len(items) > 2 %}。表达语句是使用 {{ 和 }} 包起来的,例如 {{ items[0] }}

控制语句和对应的 Python 语句的格式基本完全相同。我们支持 ifforwhile 和 try,这些语句逻辑结束的位置需要用 {% end %} 做标记。还通过 extends 和 block 语句实现了模板继承。这些在 template 模块 的代码文档中有着详细的描述。

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>123456</title>
<link href="{{static_url("css/common.css")}}" rel="stylesheet" />
{% block CSS %}{% end %}
</head>
<body> <div class="pg-header"> </div> {% block RenderBody %}{% end %} <script src="{{static_url("js/jquery-1.8.2.min.js")}}"></script> {% block JavaScript %}{% end %} </body>
</html>

layout.html

{% extends 'layout.html'%}
{% block CSS %}
<link href="{{static_url("css/index.css")}}" rel="stylesheet" />
<link href="/static/css/common.css" rel="stylesheet" />
{% end %} {% block RenderBody %}
<h1>Index</h1> {% end %} {% block JavaScript %} {% end %}

index

#!/usr/bin/env python
# -*- coding:utf-8 -*- import tornado.ioloop
import tornado.web class MainHandler(tornado.web.RequestHandler):
def get(self):
self.render('index.html') settings = {
'template_path': 'template',
'static_path': 'static',
'static_url_prefix': '/static/',
} application = tornado.web.Application([
(r"/index", MainHandler),
], **settings) if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()

在模板中默认提供了一些函数、字段、类以供模板使用:

  • escapetornado.escape.xhtml_escape 的別名
  • xhtml_escapetornado.escape.xhtml_escape 的別名
  • url_escapetornado.escape.url_escape 的別名
  • json_encodetornado.escape.json_encode 的別名
  • squeezetornado.escape.squeeze 的別名
  • linkifytornado.escape.linkify 的別名
  • datetime: Python 的 datetime 模组
  • handler: 当前的 RequestHandler 对象
  • requesthandler.request 的別名
  • current_userhandler.current_user 的別名
  • localehandler.locale 的別名
  • _handler.locale.translate 的別名
  • static_url: for handler.static_url 的別名
  • xsrf_form_htmlhandler.xsrf_form_html 的別名

Tornado默认提供的这些功能其实本质上就是 UIMethodUIModule,我们也可以自定义从而实现类似于Django的simple_tag的功能:

1、定义

# uimethods.py

def tab(self):
return 'UIMethod'

uimethods.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from tornado.web import UIModule
from tornado import escape class custom(UIModule): def render(self, *args, **kwargs):
return escape.xhtml_escape('<h1>chenchao</h1>')

uimodules.py

2、注册

#!/usr/bin/env python
# -*- coding:utf-8 -*-
#!/usr/bin/env python
# -*- coding:utf-8 -*- import tornado.ioloop
import tornado.web
from tornado.escape import linkify
import uimodules as md
import uimethods as mt class MainHandler(tornado.web.RequestHandler):
def get(self):
self.render('index.html') settings = {
'template_path': 'template',
'static_path': 'static',
'static_url_prefix': '/static/',
'ui_methods': mt,
'ui_modules': md,
} application = tornado.web.Application([
(r"/index", MainHandler),
], **settings) if __name__ == "__main__":
application.listen(8009)
tornado.ioloop.IOLoop.instance().start() main.py

main.py

3、使用

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<link href="{{static_url("commons.css")}}" rel="stylesheet" />
</head>
<body>
<h1>hello</h1>
{% module custom(123) %}
{{ tab() }}
</body>

index.html

四、实用功能

1、静态文件

对于静态文件,可以配置静态文件的目录和前段使用时的前缀,并且Tornaodo还支持静态文件缓存。

#!/usr/bin/env python
# -*- coding:utf-8 -*- import tornado.ioloop
import tornado.web
import uimodules as md
import uimethods as mt class MainHandler(tornado.web.RequestHandler):
def get(self):
self.render('index.html') settings = {
'template_path': 'template',
'static_path': 'static',
'static_url_prefix': '/static/',
'ui_methods': mt,
'ui_modules': md,
} application = tornado.web.Application([
(r"/index", MainHandler),
], **settings) if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()

main.py

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>123456</title>
<link href="{{static_url("css/common.css")}}" rel="stylesheet" /> </head>
<body> <div class="pg-header">
<h1>Index</h1>
</div> <script src="{{static_url("js/jquery-1.8.2.min.js")}}"></script> </body>
</html>

index.html

备注:静态文件缓存的实现

    def get_content_version(cls, abspath):

        data = cls.get_content(abspath)
hasher = hashlib.md5()
if isinstance(data, bytes):
hasher.update(data)
else:
for chunk in data:
hasher.update(chunk)
return hasher.hexdigest()

静态文件缓存源码

2、csrf

Tornado中的跨站请求伪造和Django中的相似,跨站伪造请求(Cross-site request forgery)

settings = {
"xsrf_cookies": True,
}
application = tornado.web.Application([
(r"/", MainHandler),
(r"/login", LoginHandler),
], **settings)

配置

<form action="/new_message" method="post">
{{ xsrf_form_html() }}
<input type="text" name="message"/>
<input type="submit" value="Post"/>
</form>

普通表单使用

function getCookie(name) {
var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
return r ? r[1] : undefined;
} jQuery.postJSON = function(url, args, callback) {
args._xsrf = getCookie("_xsrf");
$.ajax({url: url, data: $.param(args), dataType: "text", type: "POST",
success: function(response) {
callback(eval("(" + response + ")"));
}});
};

Ajax使用

注:Ajax使用时,本质上就是去获取本地的cookie,携带cookie再来发送请求

3、cookie

Tornado中可以对cookie进行操作,并且还可以对cookie进行签名以防止伪造。

a、基本操作

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

b、签名

Cookie 很容易被恶意的客户端伪造。加入你想在 cookie 中保存当前登陆用户的 id 之类的信息,你需要对 cookie 作签名以防止伪造。Tornado 通过 set_secure_cookie 和 get_secure_cookie 方法直接支持了这种功能。 要使用这些方法,你需要在创建应用时提供一个密钥,名字为 cookie_secret。 你可以把它作为一个关键词参数传入应用的设置中:

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!") application = tornado.web.Application([
(r"/", MainHandler),
], cookie_secret="61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=")

code

签名Cookie的本质是:

写cookie过程:

  • 将值进行base64加密
  • 对除值以外的内容进行签名,哈希算法(无法逆向解析)
  • 拼接 签名 + 加密值

读cookie过程:

  • 读取 签名 + 加密值
  • 对签名进行验证
  • base64解密,获取值内容

注:许多API验证机制和安全cookie的实现机制相同。

#!/usr/bin/env python
# -*- coding:utf-8 -*- import tornado.ioloop
import tornado.web class MainHandler(tornado.web.RequestHandler): def get(self):
login_user = self.get_secure_cookie("login_user", None)
if login_user:
self.write(login_user)
else:
self.redirect('/login') class LoginHandler(tornado.web.RequestHandler):
def get(self):
self.current_user() self.render('login.html', **{'status': ''}) def post(self, *args, **kwargs): username = self.get_argument('name')
password = self.get_argument('pwd')
if username == 'wupeiqi' and password == '':
self.set_secure_cookie('login_user', '陈超')
self.redirect('/')
else:
self.render('login.html', **{'status': '用户名或密码错误'}) settings = {
'template_path': 'template',
'static_path': 'static',
'static_url_prefix': '/static/',
'cookie_secret': 'aiuasdhflashjdfoiuashdfiuh'
} application = tornado.web.Application([
(r"/index", MainHandler),
(r"/login", LoginHandler),
], **settings) if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()

基于cookie进行用户验证

#!/usr/bin/env python
# -*- coding:utf-8 -*- import tornado.ioloop
import tornado.web class BaseHandler(tornado.web.RequestHandler): def get_current_user(self):
return self.get_secure_cookie("login_user") class MainHandler(BaseHandler): @tornado.web.authenticated
def get(self):
login_user = self.current_user
self.write(login_user) class LoginHandler(tornado.web.RequestHandler):
def get(self):
self.current_user() self.render('login.html', **{'status': ''}) def post(self, *args, **kwargs): username = self.get_argument('name')
password = self.get_argument('pwd')
if username == 'wupeiqi' and password == '':
self.set_secure_cookie('login_user', '陈超')
self.redirect('/')
else:
self.render('login.html', **{'status': '用户名或密码错误'}) settings = {
'template_path': 'template',
'static_path': 'static',
'static_url_prefix': '/static/',
'cookie_secret': 'aiuasdhflashjdfoiuashdfiuh',
'login_url': '/login'
} application = tornado.web.Application([
(r"/index", MainHandler),
(r"/login", LoginHandler),
], **settings) if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()

Tornado内部提供cookie验证

五、扩展功能

1、自定义Session

a.知识储备

类的特殊成员

#!/usr/bin/env python
# -*- coding:utf-8 -*- class Foo(object): def __getitem__(self, key):
print '__getitem__',key def __setitem__(self, key, value):
print '__setitem__',key,value def __delitem__(self, key):
print '__delitem__',key obj = Foo()
result = obj['k1']
#obj['k2'] = 'chenchao'
#del obj['k1']

b.session实现机制

#!/usr/bin/env python
# -*- coding:utf-8 -*- import tornado.ioloop
import tornado.web
from hashlib import sha1
import os, time session_container = {}

# 创建MD516进制的session_id
create_session_id = lambda: sha1('%s%s' % (os.urandom(16), time.time())).hexdigest() class Session(object): session_id = "__sessionId__" # 自定义session的key名称 def __init__(self, request):
    
# 默认先从请求信息里获取自定义的cookie值
session_value = request.get_cookie(Session.session_id)
if not session_value:
self._id = create_session_id()
else:
self._id = session_value
# 设置cookie
request.set_cookie(Session.session_id, self._id) def __getitem__(self, key):
return session_container[self._id][key] def __setitem__(self, key, value):
if session_container.has_key(self._id):
session_container[self._id][key] = value
else:
session_container[self._id] = {key: value} def __delitem__(self, key):
del session_container[self._id][key] class BaseHandler(tornado.web.RequestHandler): def initialize(self):
# 创建Session的对象,将MainHandler的对象传入
self.my_session = Session(self) # 继承自定义的BaseHandler
class MainHandler(BaseHandler): def get(self):
print self.my_session['c_user'] # 获取session的值
print self.my_session['c_card']
self.write('index') class LoginHandler(BaseHandler): def get(self):
self.render('login.html', **{'status': ''}) def post(self, *args, **kwargs): username = self.get_argument('name')
password = self.get_argument('pwd')
if username == 'chenchao' and password == '123':

# 设置session的值
self.my_session['c_user'] = 'chenchao'
self.my_session['c_card'] = '12312312309823012' self.redirect('/index')
else:
self.render('login.html', **{'status': '用户名或密码错误'}) settings = {
'template_path': 'template',
'static_path': 'static',
'static_url_prefix': '/static/',
'cookie_secret': 'aiuasdhflashjdfoiuashdfiuh',
'login_url': '/login'
} application = tornado.web.Application([
(r"/index", MainHandler),
(r"/login", LoginHandler),
], **settings) if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()

  

2、自定义模型绑定

模型绑定有两个主要功能:

  • 自动生成html表单
  • 用户输入验证

在之前学习的Django中为程序员提供了非常便捷的模型绑定功能,但是在Tornado中,一切需要自己动手!!!

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<link href="{{static_url("commons.css")}}" rel="stylesheet" />
</head>
<body>
<h1>hello</h1>
<form action="/index" method="post"> <p>hostname: <input type="text" name="host" /> </p>
<p>ip: <input type="text" name="ip" /> </p>
<p>port: <input type="text" name="port" /> </p>
<p>phone: <input type="text" name="phone" /> </p>
<input type="submit" />
</form>
</body>
</html>

Html

#!/usr/bin/env python
# -*- coding:utf-8 -*- import tornado.ioloop
import tornado.web
from hashlib import sha1
import os, time
import re class MainForm(object):
def __init__(self):
self.host = "(.*)"
self.ip = "^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$"
self.port = '(\d+)'
self.phone = '^1[3|4|5|8][0-9]\d{8}$' def check_valid(self, request):
form_dict = self.__dict__
for key, regular in form_dict.items():
post_value = request.get_argument(key)
# 让提交的数据 和 定义的正则表达式进行匹配
ret = re.match(regular, post_value)
print key,ret,post_value class MainHandler(tornado.web.RequestHandler):
def get(self):
self.render('index.html')
def post(self, *args, **kwargs):
obj = MainForm()
result = obj.check_valid(self)
self.write('ok') settings = {
'template_path': 'template',
'static_path': 'static',
'static_url_prefix': '/static/',
'cookie_secret': 'aiuasdhflashjdfoiuashdfiuh',
'login_url': '/login'
} application = tornado.web.Application([
(r"/index", MainHandler),
], **settings) if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()

由于请求的验证时,需要考虑是否可以为空以及正则表达式的复用,所以:

#!/usr/bin/env python
# -*- coding:utf-8 -*- import tornado.ioloop
import tornado.web
import re class Field(object): def __init__(self, error_msg_dict, required):
self.id_valid = False
self.value = None
self.error = None
self.name = None
self.error_msg = error_msg_dict
self.required = required def match(self, name, value):
self.name = name if not self.required:
self.id_valid = True
self.value = value
else:
if not value:
if self.error_msg.get('required', None):
self.error = self.error_msg['required']
else:
self.error = "%s is required" % name
else:
ret = re.match(self.REGULAR, value)
if ret:
self.id_valid = True
self.value = ret.group()
else:
if self.error_msg.get('valid', None):
self.error = self.error_msg['valid']
else:
self.error = "%s is invalid" % name class IPField(Field):
REGULAR = "^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$" def __init__(self, error_msg_dict=None, required=True): error_msg = {} # {'required': 'IP不能为空', 'valid': 'IP格式错误'}
if error_msg_dict:
error_msg.update(error_msg_dict) super(IPField, self).__init__(error_msg_dict=error_msg, required=required) class IntegerField(Field):
REGULAR = "^\d+$" def __init__(self, error_msg_dict=None, required=True):
error_msg = {'required': '数字不能为空', 'valid': '数字格式错误'}
if error_msg_dict:
error_msg.update(error_msg_dict) super(IntegerField, self).__init__(error_msg_dict=error_msg, required=required) class CheckBoxField(Field): def __init__(self, error_msg_dict=None, required=True):
error_msg = {} # {'required': 'IP不能为空', 'valid': 'IP格式错误'}
if error_msg_dict:
error_msg.update(error_msg_dict) super(CheckBoxField, self).__init__(error_msg_dict=error_msg, required=required) def match(self, name, value):
self.name = name if not self.required:
self.id_valid = True
self.value = value
else:
if not value:
if self.error_msg.get('required', None):
self.error = self.error_msg['required']
else:
self.error = "%s is required" % name
else:
if isinstance(name, list):
self.id_valid = True
self.value = value
else:
if self.error_msg.get('valid', None):
self.error = self.error_msg['valid']
else:
self.error = "%s is invalid" % name class FileField(Field):
REGULAR = "^(\w+\.pdf)|(\w+\.mp3)|(\w+\.py)$" def __init__(self, error_msg_dict=None, required=True):
error_msg = {} # {'required': '数字不能为空', 'valid': '数字格式错误'}
if error_msg_dict:
error_msg.update(error_msg_dict) super(FileField, self).__init__(error_msg_dict=error_msg, required=required) def match(self, name, value):
self.name = name
self.value = []
if not self.required:
self.id_valid = True
self.value = value
else:
if not value:
if self.error_msg.get('required', None):
self.error = self.error_msg['required']
else:
self.error = "%s is required" % name
else:
m = re.compile(self.REGULAR)
if isinstance(value, list):
for file_name in value:
r = m.match(file_name)
if r:
self.value.append(r.group())
self.id_valid = True
else:
self.id_valid = False
if self.error_msg.get('valid', None):
self.error = self.error_msg['valid']
else:
self.error = "%s is invalid" % name
break
else:
if self.error_msg.get('valid', None):
self.error = self.error_msg['valid']
else:
self.error = "%s is invalid" % name def save(self, request, upload_path=""): file_metas = request.files[self.name]
for meta in file_metas:
file_name = meta['filename']
with open(file_name,'wb') as up:
up.write(meta['body']) class Form(object): def __init__(self):
self.value_dict = {}
self.error_dict = {}
self.valid_status = True def validate(self, request, depth=10, pre_key=""): self.initialize()
self.__valid(self, request, depth, pre_key) def initialize(self):
pass def __valid(self, form_obj, request, depth, pre_key):
"""
验证用户表单请求的数据
:param form_obj: Form对象(Form派生类的对象)
:param request: Http请求上下文(用于从请求中获取用户提交的值)
:param depth: 对Form内容的深度的支持
:param pre_key: Html中name属性值的前缀(多层Form时,内部递归时设置,无需理会)
:return: 是否验证通过,True:验证成功;False:验证失败
""" depth -= 1
if depth < 0:
return None
form_field_dict = form_obj.__dict__
for key, field_obj in form_field_dict.items():
print key,field_obj
if isinstance(field_obj, Form) or isinstance(field_obj, Field):
if isinstance(field_obj, Form):
# 获取以key开头的所有的值,以参数的形式传至
self.__valid(field_obj, request, depth, key)
continue
if pre_key:
key = "%s.%s" % (pre_key, key) if isinstance(field_obj, CheckBoxField):
post_value = request.get_arguments(key, None)
elif isinstance(field_obj, FileField):
post_value = []
file_list = request.request.files.get(key, None)
for file_item in file_list:
post_value.append(file_item['filename'])
else:
post_value = request.get_argument(key, None) print post_value
# 让提交的数据 和 定义的正则表达式进行匹配
field_obj.match(key, post_value)
if field_obj.id_valid:
self.value_dict[key] = field_obj.value
else:
self.error_dict[key] = field_obj.error
self.valid_status = False class ListForm(object):
def __init__(self, form_type):
self.form_type = form_type
self.valid_status = True
self.value_dict = {}
self.error_dict = {} def validate(self, request):
name_list = request.request.arguments.keys() + request.request.files.keys()
index = 0
flag = False
while True:
pre_key = "[%d]" % index
for name in name_list:
if name.startswith(pre_key):
flag = True
break
if flag:
form_obj = self.form_type()
form_obj.validate(request, depth=10, pre_key="[%d]" % index)
if form_obj.valid_status:
self.value_dict[index] = form_obj.value_dict
else:
self.error_dict[index] = form_obj.error_dict
self.valid_status = False
else:
break index += 1
flag = False class MainForm(Form): def __init__(self):
# self.ip = IPField(required=True)
# self.port = IntegerField(required=True)
# self.new_ip = IPField(required=True)
# self.second = SecondForm()
self.fff = FileField(required=True)
super(MainForm, self).__init__() #
# class SecondForm(Form):
#
# def __init__(self):
# self.ip = IPField(required=True)
# self.new_ip = IPField(required=True)
#
# super(SecondForm, self).__init__() class MainHandler(tornado.web.RequestHandler):
def get(self):
self.render('index.html')
def post(self, *args, **kwargs):
# for i in dir(self.request):
# print i
# print self.request.arguments
# print self.request.files
# print self.request.query
# name_list = self.request.arguments.keys() + self.request.files.keys()
# print name_list # list_form = ListForm(MainForm)
# list_form.validate(self)
#
# print list_form.valid_status
# print list_form.value_dict
# print list_form.error_dict # obj = MainForm()
# obj.validate(self)
#
# print "验证结果:", obj.valid_status
# print "符合验证结果:", obj.value_dict
# print "错误信息:"
# for key, item in obj.error_dict.items():
# print key,item
# print self.get_arguments('favor'),type(self.get_arguments('favor'))
# print self.get_argument('favor'),type(self.get_argument('favor'))
# print type(self.get_argument('fff')),self.get_argument('fff')
# print self.request.files
# obj = MainForm()
# obj.validate(self)
# print obj.valid_status
# print obj.value_dict
# print obj.error_dict
# print self.request,type(self.request)
# obj.fff.save(self.request)
# from tornado.httputil import HTTPServerRequest
# name_list = self.request.arguments.keys() + self.request.files.keys()
# print name_list
# print self.request.files,type(self.request.files)
# print len(self.request.files.get('fff')) # obj = MainForm()
# obj.validate(self)
# print obj.valid_status
# print obj.value_dict
# print obj.error_dict
# obj.fff.save(self.request)
self.write('ok') settings = {
'template_path': 'template',
'static_path': 'static',
'static_url_prefix': '/static/',
'cookie_secret': 'aiuasdhflashjdfoiuashdfiuh',
'login_url': '/login'
} application = tornado.web.Application([
(r"/index", MainHandler),
], **settings) if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start() Form验证框架

Form验证框架

Tornado基本使用的更多相关文章

  1. Python(九)Tornado web 框架

    一.简介 Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本.这个 Web 框架看起来有些像web.py 或者 Google 的 webapp,不过 ...

  2. 使用tornado,我们可以做什么?

    以下介绍都是建立在python2.x的基础上面,tornado使用任意版本皆可. 如果我们需要对外提供一个http server(web api)/websocket server时,我们都可以使用t ...

  3. tornado session

    [转]tornado入门 - session cookie 和session 的区别: 1.cookie数据存放在客户的浏览器上,session数据放在服务器上. 2.cookie不是很安全,别人可以 ...

  4. tornado template

    若果使用Tornado进行web开发可能会用到模板功能,页面继承,嵌套... 多页应用模板的处理多半依赖后端(SPA就可以动态加载局部视图),就算是RESTfull的API设计,也不妨碍同时提供部分模 ...

  5. tornado上手

    http://www.tornadoweb.org/en/stable/ http://www.cnblogs.com/fanweibin/p/5418697.html import tornado. ...

  6. tornado+sqlalchemy+celery,数据库连接消耗在哪里

    随着公司业务的发展,网站的日活数也逐渐增多,以前只需要考虑将所需要的功能实现就行了,当日活越来越大的时候,就需要考虑对服务器的资源使用消耗情况有一个清楚的认知.     最近老是发现数据库的连接数如果 ...

  7. centos 6.7 搭建tornado + nginx + supervisor的方法(已经实践)

    首先,本来不想写这篇博客了,但是我测试了很多网上的例子包括简书的,全不行,我总结原因是自己太笨,搞了俩个晚上,后来决定,自己还是写一篇记录下来,保证自己以后使用 环境: centos6.7 64 py ...

  8. tornado中将cookie值设置为json字符串

    不熟悉,找了很久,能FQ的话, https://groups.google.com/forum/#!topic/python-tornado/9Y--NgwjP_w 2楼有解释. tornado.es ...

  9. tornado 异步调用系统命令和非阻塞线程池

    项目中异步调用 ping 和 nmap 实现对目标 ip 和所在网关的探测 Subprocess.STREAM 不用担心进程返回数据过大造成的死锁, Subprocess.PIPE 会有这个问题. i ...

  10. 离线安装 Python 2.7, paramiko 和 tornado

    无非就是离线安装, 步骤比较繁琐, 记录一下. 需求很简单, 一个离线安装的 Python, 能跑 tornado 和 paramiko 1. 离线安装 Python 2.7 .tgz cd Pyth ...

随机推荐

  1. 《sed的流艺术之三》-linux命令五分钟系列之二十三

    本原创文章属于<Linux大棚>博客,博客地址为http://roclinux.cn.文章作者为rocrocket. 为了防止某些网站的恶性转载,特在每篇文章前加入此信息,还望读者体谅. ...

  2. 【笔记-前端】div+css排版基础,以及错误记录

    现在的网站对于前端的排版已经逐渐不使用<table>,而是使用div+css. 使用这种方法的最大好处就在于在维护页面时,可以只维护css而不去改动html. 可是这种方式对于初学者来说可 ...

  3. js 判断数组中是否存在

    /* 判断数组中是否存在 var somearray = ["mon", "tue", "wed", "thur"] s ...

  4. jquery 缓冲加载图片插件 jquery.lazyload

    第一:加入jquery 第二:加入jquery.lazy.load.js文件 第三:在网页中加<script> $(document).ready(function(){ $(" ...

  5. javaScript中with的用法

    1 JavaScript中的with语句的作用是为逐级的对象访问提供命名空间式的速写方式, 也就是在指定的代码区域, 直接通过节点名称调用对象 初次接触到with用法,是这样一段代码: 1 2 3 4 ...

  6. django之JavaScript的简单学习2

    前言:ajax预备知识:json进阶 1.JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.JSON是用字符串来表示Javascript对象: 请大家记住一 ...

  7. mongodb篇二:mongodb克隆远程数据库,去重查询的命令及对应java语句

    http://blog.csdn.net/qkxh320/article/details/16115671 1.首先操作mongodb最基本命令:: show databases;           ...

  8. POJ 1459 Power Network 最大流(Edmonds_Karp算法)

    题目链接: http://poj.org/problem?id=1459 因为发电站有多个,所以需要一个超级源点,消费者有多个,需要一个超级汇点,这样超级源点到发电站的权值就是发电站的容量,也就是题目 ...

  9. ajax error函数

    老是去百度 还是自己记下来吧 $.ajax({ url: '/AJAX请求的URL', success: function (data) { alert(data); }, error: functi ...

  10. Java数据库连接关闭后无法启动

    错误如下: java.sql.SQLException: No operations allowed after connection closed. at com.mysql.jdbc.Connec ...