Tornado-基于正则的路由和动态分页

概览

这一小节涉及了三部分内容:

1.动态分页设计

2.基本的路由系统以及基于正则的路由

3.模块引擎的继承和导入

4.web项目文件夹和ReuquestHandler的分类

5.跨站脚本攻击

文件结构

Python代码

start.py

from tornado.ioloop import IOLoop
import tornado.web
from controllers import account
from controllers import home
from controllers import extend

settings = {
        "template_path": "views",  # 配置html文件路径
        "static_path": "statics",  # 配置静态文件路径
    }

# 路由映射
# 基于正则路由是为了解决基本路由僵化的一一对应问题,可以实现一个类处理多种url
application = tornado.web.Application([
    #
    (r"/index/?(?P<page>\d*)", home.IndexHandler),
    (r"/login", account.LoginHandler),
    # 模板继承与导入
    (r"/extend/index", extend.ExtendIndexHandler),
    (r"/extend/home", extend.ExtendHomeHandler),
], **settings)

# 启动服务端
if __name__ == "__main__":
    application.listen(8888)
    IOLoop.instance().start()

controllers -account.py -extend.py -home.py

import tornado.web

class LoginHandler(tornado.web.RequestHandler):
    def get(self):
        pass

class LogoutHandler(tornado.web.RequestHandler):
    def get(self):
        pass

class RegisterHandler(tornado.web.RequestHandler):
    def get(self):
        pass

account.py

import tornado.web

class ExtendIndexHandler(tornado.web.RequestHandler):
    def get(self):
        self.render(‘extend/index.html‘)

class ExtendHomeHandler(tornado.web.RequestHandler):
    def get(self):
        self.render(‘extend/home.html‘)

extend.py

import tornado.web
from commons.pagination import Pagination

INFO_LIST = [
    {‘name‘: ‘yeff‘, ‘age‘: ‘23‘},
]
for i in range(99):
    INFO_LIST.append({
        ‘name‘: ‘a‘+str(i), ‘age‘: ‘0‘+str(i)
    })

class IndexHandler(tornado.web.RequestHandler):
    def get(self, page):
        pn = Pagination(page, 5, INFO_LIST)
        str_pages = pn.get(‘/index‘)
        display_list = pn.items[pn.start_item:pn.end_item]
        self.render("home/index.html", info_list=display_list, current_page=page, page_nums=str_pages)

    def post(self, page):
        # 之前提交时,action连接的是/index,因此在没有添加current_page参数之前,page都只会为空字符串
        name = self.get_argument(‘name‘)
        age = self.get_argument(‘age‘)
        _dic = {‘name‘: name, ‘age‘: age}
        INFO_LIST.append(_dic)
        self.redirect("/index/" + page)

home.py

commons -Pagination.py

class Pagination(object):
    def __init__(self, current_page, items_per_page, items):
        try:
            current_page = int(current_page)
            assert current_page > 0
            assert current_page < len(items)
        except:
            current_page = 1
        self.current_page = current_page
        self.items = items
        self.per_page = items_per_page

    @property
    def start_item(self):
        # 设若有n个元素,每页显示a个,则第x页的元素列表就是
        # 前一页的最后一个元素是第(x-1)*a个元素,下一个就是第[(x-1)*a]+1个元素,序号就是(x-1)*a
        return (self.current_page - 1) * self.per_page

    @property
    def end_item(self):
        # 当前页的最后一个元素是第ax个,序号就是ax-1,但因为切片操作留头切尾,因此还要再+1,结果就是ax
        return self.current_page * self.per_page

    # Create page numbers
    def get(self, base_url=‘‘):
        actual_pages, _remainder = divmod(len(self.items), self.per_page)
        actual_pages += 1 if _remainder > 0 else 0

        start = self.current_page - 5
        end = self.current_page + 5

        # 防止页码变成负数,以及大于实际页数
        # 这里的条件限制类似放大镜那一节防止超出边界时的设置
        # 这里用到了多重赋值和三元运算符
        # 多重赋值本质就是tuple packing(元组打包)和 Sequence unpacking(序列解包)
        # A = Y if X else Z
        # 只有当X为真时才会执行表达式Y,而只有当X为假时,才会执行表达式Z
        start, end = (1, 10) if start <= 0 else (start, end)
        start, end = (end-10, actual_pages) if end >= actual_pages else (start, end)

        pages_list = []

        # 首页标签
        first_page = ‘<a href="%s/1">首页</a>‘ % base_url
        # 上一页标签
        prev_page = ‘<a href="%s/%s">上一页</a>‘ % (base_url, self.current_page - 1 if self.current_page > 1 else self.current_page )

        pages_list.append(first_page+prev_page)
        for _ in range(start, end + 1):
            if _ == self.current_page:
                _str = ‘<a class="active" href="%s/%s">%s</a>‘ % (base_url, _, _)
            else:
                _str = ‘<a href="%s/%s">%s</a>‘ % (base_url, _, _)
            pages_list.append(_str)

        # 下一页标签
        next_page = ‘<a href="%s/%s">下一页</a>‘ % (base_url, self.current_page + 1 if self.current_page < actual_pages else self.current_page)
        # 尾页标签
        last_page = ‘<a href="%s/%s">首页</a>‘ % (base_url, actual_pages)
        pages_list.append(next_page+last_page)

        # 跳转标签和输入框
        # 注意嵌套情况下引号的使用:onclick后的引号,其参数的引号
        # 注意js的形参不能是已占用的关键字this
        jump = """<input type=‘text‘/><a onclick="Jump(‘%s‘,this);">跳转</a>""" % base_url
        script = """<script>
            function Jump(base_url, ths){
                val = ths.previousElementSibling.value;
                if(val.trim().length>0){
                    location.href=base_url + "/" + val;
                }
            }
        </script>"""
        pages_list.append(jump+script)

        pages = ‘‘.join(pages_list)
        return pages

HTML文件

home -index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
    <style>
        .pages a{
            display:inline-block;
            padding:5px;
            margin:5px;
            background-color:yellow;
        }
        .pages .active {background-color:red;}
    </style>
</head>
<body>
    <h1>输入数据</h1>
    <form action="/index/{{ current_page }}" method="post">
        <input type="text" name="name">
        <input type="text" name="age">
        <input type="submit" value="提交">
    </form>
    <h1>展示数据</h1>
    <table border="1">
        <th>
            <tr>
                <td>姓名</td>
                <td>年龄</td>
            </tr>
        </th>
        <tbody>
            {% for item in info_list %}
            <tr>
                <!--raw行就是一个XSS跨站脚本攻击的一个例子,本来tornado内部会对js脚本默认进行处理,避免脚本攻击‘-->
                <!--如果加上raw的话,就会以输入的格式进行处理-->
                <!--如:输入<script>alert(1);</script>-->
                <!--提交后,渲染页面时,遇到这一行就会执行该代码-->
                <!--使用toranado的默认方式就好-->
                <!--<td>{% raw item[‘name‘] %}</td>-->
                <td>{{ item[‘name‘] }}</td>
                <td>{{ item[‘age‘] }}</td>
            </tr>
            {% end %}
        </tbody>
    </table>
    <div class="pages">
        {% raw page_nums %}
    </div>
</body>
</html>

主页面(动态分页)

plates -form.html -layout.html

<form>
    <!--模板导入-->
    <h1>Form To Be Included</h1>
    <input type="text"/>
    <input type="password"/>
    <input type="button">
    <input type="submit">
</form>

form.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>模板继承</title>
</head>
<style>
    *{color:white;}
    .pg-header{
        width:800px;
        height:200px;
        background-color:gray;
    }
    .pg-content{
        width:800px;
        height:500px;
        background-color:green;
    }
    .pg-footer{
        width:800px;
        height:100px;
        background-color:orange;
    }
</style>
        {% block css %}{% end %}
<body>
    <div class="pg-header"></div>
    <div class="pg-content">
        {% block body %}{% end %}
    </div>
    <div class="pg-footer"></div>
<script> function MainPage(){alert("Layout");}</script>
{% block js %}{% end %}
</body>
</html>

layout.html

extend -home.html -index.html(主要是为了应用模板文件,展示模板引擎的继承和导入)

{% extends ‘../plates/layout.html‘ %}

{% block css %}
    <style>a{color:yellow;}</style>
{%  end  %}

{% block body %}
    <h1>Home Page</h1>
    <a>Home page</a>
{%  end  %}

{% block js %}
    <script>
        alert("Home  page.");
    </script>
{%  end  %}

home.html

{% extends ‘../plates/layout.html‘ %}

{% block body %}
    <h1>Index Page</h1>
    <a>Index Page</a>
    {% include ‘../plates/form.html‘%}
{%  end  %}

{% block css %}
    <style>
        a{color:black;}
    </style>
{%  end  %}

{% block js %}
    <script>
        alert("Index page.");
    </script>
{%  end  %}

index.html

时间: 2024-10-12 07:39:25

Tornado-基于正则的路由和动态分页的相关文章

第二百六十三也,Tornado框架-基于正则的动态路由映射分页

Tornado框架-基于正则的动态路由映射分页 分页基本显示数据 第一步.设置正则路由映射配置,(r"/index/(?P<page>\d*)", index.indexHandler),正则匹配访问路径,访问录index/后面可以是可以是0个或多个数字第二步.配置逻辑处理方法,get()方法里显示对应的页面,并传值一个SHUJU全局变量列表到html模板,这个全局变量列表里是字典显示的数据第三步.在html模板里用模板语言,循环这个列表里的字典,显示到表格里第四步.设置用

Route 53更新 - 域名注册、基于地理位置的路由与价格下调

AmazonRoute 53是一项高可用性及高可扩展性域名服务(简称DNS),其中还包括一项强大的运行状况检查服务.如今,我们利用域名注册与管理以及基于地理位置的DNS支持能力对Route 53进行了深度扩展.我们还对Route 53查询价格进行了下调!现在就让我们近距离一探这些项目的价值所在. 域名注册与管理 早在1995年,我就注册了自己的第一个域名!在那个时候,域管理与注册的方方面面在处理上都极为困难.成本高昂而且需要全部以手动方式完成.在想到一个好名称之后,大家需要说服一到两位懂技术的朋

LayUI分页,LayUI动态分页,LayUI laypage分页,LayUI laypage刷新当前页

LayUI分页,LayUI动态分页,LayUI laypage分页,LayUI laypage刷新当前页 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ?Copyright 蕃薯耀 2017年8月1日 http://www.cnblogs.com/fanshuyao/ 效果图: 一.引用js依赖

Linux 基于策略的路由

Linux 基于策略的路由(Linux Policy Routing) Linux 有传统的基于数据包目的地址的路由算法,和新的基于策略的路由算法新算法优点:支持多个路由表,支持按数据报属性(源地址.目的地址.协议.端口.数据包大小.内容等)选择不同路由表 # 查看规则命令,后面可跟其它参数,默认为 show(list) 显示全部ip rule 系统默认有3条记录0: from all lookup local32766: from all lookup main32767: from all

YAHOO.widget.DataTable 动态分页。

Server:服务器端的代码输出数据格式如下: {"total":"392","rows":[{"areaid":"1","areaname":"北京","parentid":"0","arrparentid":"0","child":"0",&qu

Asp.net MVC 基于Area的路由映射

对于一个较大规模的Web应用,我们可以从功能上通过Area将其划分为较小的单元.每个Area相当于一个独立的子系统,具有一套包含Models.Views和Controller在内的目录结构和配置文件.一般来说,每个Area具有各自的路由规则(URL模版上一般会体现Area的名称),而基于Area的路由映射通过AreaRegistration进行注册. 一.创建Areas 右键工程 -> 添加->区域 添加后生成一套包含Models.Views和Controller在内的目录结构和配置文件:只是

基于 Spring 和 iBATIS 的动态可更新多数据源持久层

前言 我们时常会遇到一些 web 项目,需要从不同的数据源中抓取数据来进行分析,而这些数据源是有可能变化的,需要用户来进行动态的维护和添加.可是,大多数的 web 程序使用了应用服务器或者容器中间件来管理数据源的生命周期,因此数据源的变化自然不能够独立于程序,而需要由专业人士去进行维护,必要时还需要重新发布程序来适应数据源的变化,而且数据源的个数.数据库的类型也都会有所限制. 那么怎样才可以突破以上这些局限,彻底实现由用户远程对数据源进行维护和管理的需求呢?本文提出了一个有效的解决方案,该方案的

jquery动态分页

最近一直研究jquery的分页效果,刚刚弄好了一个,拿出来与大家分享.分页效果与时光网的差不多. 网址:http://www.mtime.com/movie/news/all/ 先在aspx页面放置一个<div class="pageDivs"></div> ,这个是用来存放分页的. 然后建一个page.js文件,具体代码如下(js中用到的css类是自己设置的,这里就不给出了,具体的大家可以自己设置一下css样式): $(document).ready(func

正则匹配路由

正则匹配路由 在 web 开发中,可能会出现限制用户访问规则的场景,那么这个时候就需要用到正则匹配,根据自己的规则去限定请求参数再进行访问 具体实现步骤为: 导入转换器基类:在 Flask 中,所有的路由的匹配规则都是使用转换器对象进行记录 自定义转换器:自定义类继承于转换器基类 添加转换器到默认的转换器字典中 使用自定义转换器实现自定义匹配规则 代码实现 导入转换器基类 from werkzeug.routing import BaseConverter 自定义转换器 # 自定义正则转换器 c