Tornado基本应用

Posted 青山应回首

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Tornado基本应用相关的知识,希望对你有一定的参考价值。

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

 

以上是关于Tornado基本应用的主要内容,如果未能解决你的问题,请参考以下文章

tornado基本使用一

基本介绍与Web应用结构

tornado 启动WSGI应用(Flask)使用多线程将同步代码变成异步

有没有一种好方法可以将 pychecker/pylint 应用于 Tornado 模板中的 python 代码?

tornado服务器实现原理

如何在 Tornado 应用程序中检测长阻塞函数