• [Python笔记]第十六篇:web框架之Tornado


    Tornado是一个基于python的web框架,xxxxx

     安装

    python -m pip install tornado

    第一个Tornado程序

     安装完毕我们就可以新建一个app.py文件,放入下面的代码直接运行就可以了,然后在浏览器访问127.0.0.1:8888

    import tornado.ioloop
    import tornado.web
    
    class MainHandler(tornado.web.RequestHandler):
        def get(self):
            self.write("Hello, world")
    
    application = tornado.web.Application([
        (r"/", MainHandler),
    ])
    
    if __name__ == "__main__":
        application.listen(8888)
        tornado.ioloop.IOLoop.instance().start()

     tornado执行过程:

    • 第一步:执行脚本,监听 8888 端口
    • 第二步:浏览器客户端访问 /index  -->  http://127.0.0.1:8888/index
    • 第三步:服务器接受请求,并交由对应的类处理该请求
    • 第四步:类接受到请求之后,根据请求方式(post / get / delete ...)的不同调用并执行相应的方法
    • 第五步:方法返回值的字符串内容发送浏览器

    路由系统

    路由系统执行过程是:

    用户访问一个指定url(如:www.abc.org/index)   ---->  路由系统去匹配url找到Handler  ---->  Handler处理用户请求(get/post)

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

    顺带提一句,Tornado自己基于socket实现Web服务,Django等需要依赖其他的wsgi

    import tornado.web
    
    settings = {
        'template_path': 'views',
        'static_path': 'static',
    }
    
    
    class IndexHandler(tornado.web.RequestHandler):
        def get(self,page=None):
            pass
        
        def post(self, *args, **kwargs):
            pass
    
    
    application = tornado.web.Application([
        (r"/", IndexHandler),
        (r"/index/", IndexHandler),
    ], **settings)
    
    
    if __name__ == "__main__":
        application.listen(8000)
        tornado.ioloop.IOLoop.instance().start()
    View Code

     Tornado中原生支持二级域名的路由,如:

     模板引擎

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

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

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

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

    escape: tornado.escape.xhtml_escape 的別名
    xhtml_escape: tornado.escape.xhtml_escape 的別名
    url_escape: tornado.escape.url_escape 的別名
    json_encode: tornado.escape.json_encode 的別名
    squeeze: tornado.escape.squeeze 的別名
    linkify: tornado.escape.linkify 的別名
    datetime: Python 的 datetime 模组
    handler: 当前的 RequestHandler 对象
    request: handler.request 的別名
    current_user: handler.current_user 的別名
    locale: handler.locale 的別名
    _: handler.locale.translate 的別名
    static_url: for handler.static_url 的別名
    xsrf_form_html: handler.xsrf_form_html 的別名

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

    母板

    1.定义

     

    母板完整代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>抽屉新热榜-聚合每日热门、搞笑、有趣资讯</title>
        <link type="text/css" rel="stylesheet" href="{{ static_url('css/common.css') }}" />
        <!--<link rel="stylesheet" href='{{static_url("plugins/bootstrap3/css/bootstrap.css") }}' />-->
    </head>
    <body>
        <div class="top">
            <div class="top-content">
                <img class="logo" src="/static/pic/logo.png">
                <div class="action-menu">
                    <ul class="nav-ul">
                        <li class="nav-li"><a href="/">全部</a></li>
                        <li class="nav-li"><a>42区</a></li>
                        <li class="nav-li"><a>段子</a></li>
                        <li class="nav-li"><a>图片</a></li>
                        <li class="nav-li"><a>挨踢1024</a></li>
                        <li class="nav-li"><a>你问我答</a></li>
                    </ul>
                </div>
                <div class="search-ground">
                    <span class="search-ico"></span>
                </div>
                <div>
                    <form action="https://www.sogou.com/qurey" name="qurey" method="get">
                        <input type="text" class="search-box">
                    </form>
                </div>
                <div>
                    {% if user_info["is_login"] %}
                        <div class="nav-2">
                            <a style="text-decoration: none;color: white" href="/user/link/saved/1" id="loginUserNc" class="userPro-Box" style="color: white">
                                <img src="http://img2.chouti.com/CHOUTI_05B313F703D34646848BCC5571510683_W148H148=30x30).jpg" id="userProImg">
                                <span class="u-nick" id="userProNick">{{user_info["username"]}}</span>
                                <em id="userProArr"></em>
                            </a>
                            <div class="nav-2"><a style="color: #d9edf7" href="/logout">退出</a></div>
                        </div>
                    {% else %}
                        <div class="nav-2"><a href="/login">登录</a></div>
                        <div class="nav-2"><a href="/reg">注册</a></div>
                    {% end %}
                </div>
    
    
    
    
    
            </div>
        </div>
        <div class="background">
            <div class="main-content">
                    {% block middle %}{% end %}
                <div class="footer">
                    <div class="footer-item">
                        <hr>
                        <a >关于我们</a>
                        <span>|</span>
                        <a>联系我们</a>
                        <span>|</span>
                        <a>服务条款</a>
                        <span>|</span>
                        <a>隐私政策</a>
                        <span>|</span>
                        <a>抽屉新热榜工具</a>
                        <span>|</span>
                        <a>下载客户端</a>
                        <span>|</span>
                        <a>意见与反馈</a>
                        <span>|</span>
                        <a>友情链接</a>
                        <span>|</span>
                        <a>公告</a>
                        <span>|</span>
                        <img src="http://dig.chouti.com/images/ct_rss.gif">
                    </div>
                    <div class="footer-item2">
                        <a target="_blank" href="http://www.gozap.com/"><img class="foot_e" src="http://dig.chouti.com/images/gozap-logo-50_15.gif"></a>
                        <span class="foot_d">旗下站点</span>
                        <span class="foot_a">&copy; 2016 chouti.com</span>
                        <a target="_blank" href="http://www.miibeian.gov.cn/" class="foot_b">京ICP备09053974号-3 京公网安备 110102004562</a>
                        <div style="margin-top:6px; text-align: center">版权所有:北京格致璞科技有限公司</div>
                    </div>
                </div>
            </div>
        </div>
    </body>
    </html>
    View Code

    2.使用

     

    子板完整代码

    {% extends '../master/layout.html' %}
    
    {% block middle %}
    <div class="left">
        <div class="nav-top-area">
            <div class="child-nav">
                <div class="hotbtn">
                    <a href="/all/hot/recent/1" hidefocus="false" >最热</a>
                </div>
                <div class="newbtn">
                    <a href="/all/new/1" hidefocus="false" >最新</a>
                </div>
                <div class="personbtn">
                    <a href="/all/man/1" hidefocus="false" >人类发布</a>
                </div>
            </div>
    
            <div href="javascript:;" class="publish-btn">
                <!--<a class="ico n1"></a><a class="n2">发布</a>-->
                <a class="publish-icon" href="/publish">发布</a>
            </div>
    
            <div class="sort-nav">
                <a href="/all/hot/recent/1" hidefocus="false" class="active hotbtn" style="color: #b4b4b4;">即时排序</a>
                <a href="/all/hot/24hr/1" hidefocus="false" class="newbtn" style="color: #390;;">24小时</a>
                <a href="/all/hot/72hr/1" hidefocus="false" class="newbtn" style="color: #390;;">3天</a>
            </div>
        </div>
        <div class="content-list">
        {% for new in news_list %}
            <div class="item">
                <div class="news-pic">
                    <img src="{{new['post_img']}}">
                </div>
                <div class="part1">
                    <a>{{new['post_title']}}</a>
                    <span>douban.com</span>
                    <span>42区</span>
                </div>
                <div class="part2">
                    <span>{{new['post_content']}}</span>
                </div>
            </div>
        {% end %}
        </div>
        <div class="pager">
            <!--阻止转义-->
            {% raw str_page %}
        </div>
    </div>
    <div class="right">
                    <div class="chat-area">
                        <img src="/static/pic/chouti-chat.png">
                    </div>
                    <div style="height: 581px;  312px; margin-top: 20px; margin-bottom: 20px;">
                        <img src="/static/pic/top24.png">
                    </div>
                    <div style="height: 200px;  300px">
                        <img src="/static/pic/ad_c155.jpg">
                    </div>
                </div>
    {% end %}
    View Code

    3.include

    include可以吧常用的小部件如登录框写在一个html文件里

    让其他页面直接调用,提高代码的复用性

    一个网页既调用母板 内部内容直接调用include的例子:

    {% extends '../master/layout.html' %}
    {% block middle %}
        {% include '../include/login.html' %}
    {% end %}

    4.模板语言里的if判断和for循环

    for循环

    对于Handler里面post或者get方法里面render时候传入一个news_list的字典

    模板语言循环解析他

    例子:

        <div class="content-list">
        {% for new in news_list %}
            <div class="item">
                <div class="news-pic">
                    <img src="{{new['post_img']}}">
                </div>
                <div class="part1">
                    <a>{{new['post_title']}}</a>
                    <span>douban.com</span>
                    <span>42区</span>
                </div>
                <div class="part2">
                    <span>{{new['post_content']}}</span>
                </div>
            </div>
        {% end %}
        </div>
    View Code

    if判断

    可以根据接收到的判断显示还是不显示某个html代码块

    例子:

    <div>
        {% if user_info["is_login"] %}
            <div class="nav-2">
                <a style="text-decoration: none;color: white" href="/user/link/saved/1" id="loginUserNc" class="userPro-Box" style="color: white">
                    <img src="http://img2.chouti.com/CHOUTI_05B3131510683_W148H148=30x30).jpg" id="userProImg">
                    <span class="u-nick" id="userProNick">{{user_info["username"]}}</span>
                    <em id="userProArr"></em>
                </a>
                <div class="nav-2"><a style="color: #d9edf7" href="/logout">退出</a></div>
            </div>
        {% else %}
            <div class="nav-2"><a href="/login">登录</a></div>
            <div class="nav-2"><a href="/reg">注册</a></div>
        {% end %}
    </div>
    View Code

     自定义UIMethod以UIModule

    a.定义

    # 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>wupeiqi</h1>')
            #return escape.xhtml_escape('<h1>wupeiqi</h1>')
    
    uimodules.py
    uimodules.py

    b.注册

    #!/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()
    View Code

    c.使用

    <!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>
    View Code

    附:一个比较规范的Tornado project layout

     

    有关cookie,session,验证码,表单验证,csrf,xss,ajax我们将在下一篇博文里面继续探讨

  • 相关阅读:
    数据库必知知识
    Shiro+easyUI+SpringMVC实现登录认证
    Java设计模式总结
    MyBatis之分页插件(PageHelper)工作原理
    Redis应用之[限制访问频率]
    Oracle最新的Sql笔试题及答案
    Shiro源码分析之SecurityManager对象获取
    Spring之BeanFactory和FactoryBean接口的区别
    Spring中使用的设计模式
    Spring之事件监听(观察者模型)
  • 原文地址:https://www.cnblogs.com/yaohan/p/5717819.html
Copyright © 2020-2023  润新知