Tornado框架03-路由系统

Tornado中支持两种路由系统, 正则路由系统以及二级域名路由系统.

# 默认路由系统, 根据url的不容调用不同的类
application = tornado.web.Application([
    (r"/index/(?P<page>\d*)", home.IndexHandle),
], **settings)

#二级路由匹配
application.add_handlers("test.ming.com",[
    (r"/index/(?P<page>\d*)", home.IndexHandle)
])
  • (r"/index/(?P<page>\d*)", home.IndexHandle) 这里我们访问时候需要以类似http://127.0.0.1/index/2的方式访问, 在get或者post接受处理请求的函数应有page参数来接受访问地址最后的整数(我们稍后将根据这个做一个分页的demo)
  • 当我们加入二级域名时候, 默认访问网站执行第一个默认路由系统, 仅当我们访问设置的二级域名才会调用对应的处理器(当前代码指的是test.ming.com的域名)

接下来我们使用基于正则的路由系统来实现网页分页功能.

项目目录

**all.py文件如下: **

#!/usr/bin/env python
# -*- coding:utf-8 -*-

#利用全局变量模拟数据库所有内容
USER_LIST= [
    {'username': 'test', 'email': 'test@163.com'}
]

#利用循环生成多条数据来模拟大量数据依次便于实现分页效果
for i in range(300):
    tmp = {'username': "test - " + str(i), 'email': str(i) + "@vip.com"}
    USER_LIST.append(tmp)

**pager.py文件如下: **

#!/usr/bin/env python
# -*- coding:utf-8 -*-

# 单独用于实现分页功能的类
class Page:
    # current_page表示当前页数, all_item表示总的数据条目
    # 初始化时候将当前页数current_page与总页数all_page加入到对象中
    def __init__(self, current_page, all_item):
        # all_page表示总页数, 每页显示5条数据, more表示余数, 如果大于0则表示应多加一页才能显示完所有的数据
        all_page, more = divmod(all_item, 5)
        if more > 0:
            all_page += 1
        self.all_page = all_page

        # 捕捉异常, 防止传入非法字符冒充页数, 一旦发生异常则直接将当前页current_page设置为1, 表示默认显示第一页
        try:
            current_page = int(current_page)
        except Exception as e:
            current_page = 1

        # 如果前传入的页数小于1, 则直接默认为第一页
        if current_page < 1:
            current_page = 1
        self.current_page = current_page

    # 根据当前页在每个页面显示11个页码, 此处是开始页码
    @property
    def start_page(self):
        return (self.current_page - 1) * 5

    # 结束页码
    @property
    def end_page(self):
        return self.current_page * 5

    # 显示的页码对应的html字符串, base_url表示可定制的url跳转路径
    def page_str(self, base_url):
        # 定义list_page列表用来暂时存储所有的页码字符串
        list_page = []

        # 如果总页数小于11页, 则直接显示所有页数
        if self.all_page < 11:
            s = 0
            e = self.all_page

        # 总页数大于11页时候
        else:
            # 当前页数小于6则直接显示1到11页
            if self.current_page <= 6:
                s = 1
                e = 11

            # 当前页数大于6页时候
            else:
                # 当前页加上5也之后就大于总页数则直接显示倒数11页
                if self.current_page + 5 > self.all_page:
                    s = self.all_page - 10
                    e = self.all_page

                # 当前页数大于6页并且加上5页并不超过总页数时候, 显示当前页前后5页以及当前页
                else:
                    s = self.current_page - 5
                    e = self.current_page + 5

        # 首页设置
        first_page = '<a href="/%s/1">首页</a>' % (base_url)
        list_page.append(first_page)

        # 上一页设置
        # 当前页小于等于第一页时候, 点击上一页不做任何操作(这里理论上是不会有小于的情况)
        if self.current_page <= 1:
            pre_page = '<a href="javascript:void(0);">上一页</a>'

        # 当前页大于第一页, 点击上一页则直接跳转到上一页
        else:
            pre_page = '<a href="/%s/%s">上一页</a>' % (base_url, self.current_page - 1)
        list_page.append(pre_page)

        # 根据上边条件过滤后的页码起始位置s以及页码终止位置e来生成对应的11条页码对应的html字符串
        for p in range(s, e + 1):
            if p == self.current_page:
                tmp = '<a class="active" href="/index/%s">%s</a>' % (p, p)
            else:
                tmp = '<a href="/%s/%s">%s</a>' % (base_url, p, p)
            list_page.append(tmp)

        # 下一页设置
        # 下一页要大于或者等于最大页数时候, 不做任何操作
        if self.current_page >= self.all_page:
            next_page = '<a href="javascript:void(0);">下一页</a>'
        else:
            next_page = '<a href="/%s/%s">下一页</a>' % (base_url, self.current_page + 1)
        list_page.append(next_page)

        # 尾页设置
        last_page = '<a href="/%s/%s">尾页</a>' % (base_url, self.all_page)
        list_page.append(last_page)

        # 页面跳转
        jump_page = """<input type="text" /><a onclick='JumpTo("%s",this)'>GO</a>""" % base_url
        # 页面跳转的js代码, 本质就是location.href的使用
        jspt = """<script>
            function JumpTo(base_url,th){
                var val=th.previousElementSibling.value;
                if(val.trim().length>0){
                    location.href="/"+base_url+"/"+val
                }
            }
        </script>"""
        list_page.append(jump_page)
        list_page.append(jspt)
        return "".join(list_page)

**home.py文件如下: **

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import tornado.web
from commons.all import USER_LIST
from commons.pager import Page

class IndexHandle(tornado.web.RequestHandler):
    def get(self, c_page):
        # c_page表示url传递过来的当前页数, len(USER_LIST)表示总共有多少条数据
        pg = Page(c_page, len(USER_LIST))
        #开始页数
        start = pg.start_page
        #尾页
        end = pg.end_page
        #当前显示的数据片段
        current_list = USER_LIST[start:end]
        #传入index并返回对应的下面分页部分的html代码
        str_page = pg.page_str('index')
        #将当前显示的数据片段, 当前页数以及分页的html代码返回给浏览器
        self.render('index.html', list_info=current_list, current_page=pg.current_page, str_page=str_page)

    def post(self, c_page):
        #获取传入的username的值
        username = self.get_argument('username', None)
        #获取传入的email的值
        email = self.get_argument("email", None)
        #生成临时的字典对象, 表示一个完整的数据片段
        tmp = {'username': username, 'email': email}
        #将该数据片段加入的全局变量USER_LIST, 这里用全局变量模拟数据库获取的数据
        USER_LIST.append(tmp)
        self.redirect('/index/' + c_page)

**index.html文件如下: **

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .pager a{
            display: inline-block;
            padding: 5px;
            margin: 3px;
            background-color: aquamarine;
        }
        .pager a.active {
            background-color: crimson;
            color: aliceblue;
        }
    </style>
</head>
<body>
<h1>提交数据</h1>
<form method="post" action="/index/{{current_page}}">
    <input name="username" type="text">
    <input name="email" type="text">
    <input type="submit" value="提交">
</form>
<h1>显示数据</h1>
<table border="1">
    <thead>
    <tr>
        <th>用户名</th>
        <th>邮箱</th>
    </tr>
    </thead>
    <tbody>
    {%for tmp in list_info%}
    <tr>
        <td>{{tmp['username']}}</td>
        <td>{{tmp['email']}}</td>
    </tr>
    {%end%}
    </tbody>
</table>
<div class="pager">
    <!--加raw 以此来直接执行原始的字符串, 不做转义-->
    {%raw str_page%}
</div>
</body>
</html>

**start.py文件如下: **

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import tornado.web,tornado.ioloop
from controllers import home

if __name__ == '__main__':
    settings = {
        # 模板路径配置
        'template_path': 'views',
    }

    application = tornado.web.Application([
        (r"/index/(?P<c_page>\d*)", home.IndexHandle),
    ], **settings)
    application.listen(80)
    tornado.ioloop.IOLoop.instance().start()
运行结果-1
运行结果-2
运行结果-3
  • 这种基于正则的分页实现实际上是在根据url访问显示的当前页数, 在后台生成当前页以及当前页前后5页的html字符串, 然后将这些字符串返回给浏览器直接渲染显示
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,497评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,071评论 25 707
  • love actually is all around!这是真爱至上的整个影片主题,圣诞前夕看看温暖的爱情故事也是...
    麦子飞呀飞阅读 974评论 0 1
  • 中英文原文链接:https://github.com/Chunlin-Li/Chunlin-Li.github.i...
    雲凌禹阅读 3,804评论 1 1
  • 若我躺在凉水般月光中 若你听得见我心中忧愁 若微风吹起 若梧桐作响 你会思念我否?
    相思隔山溪不绝阅读 224评论 0 0