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

 

posted @ 2018-08-09 00:18  Mr.SSC  阅读(198)  评论(0编辑  收藏  举报