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': ''},
]
for i in range(99):
INFO_LIST.append({
'name': 'a'+str(i), 'age': ''+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
Tornado-基于正则的路由和动态分页的更多相关文章
- 第二百六十四节,Tornado框架-基于正则的动态路由映射分页数据获取计算
Tornado框架-基于正则的动态路由映射分页数据获取计算 分页基本显示数据 第一步.设置正则路由映射配置,(r"/index/(?P<page>\d*)", inde ...
- 第二百六十三节,Tornado框架-基于正则的动态路由映射
Tornado框架-基于正则的动态路由映射 1.在路由映射条件里用正则匹配访问路径后缀2.给每一个正则匹配规则(?P<设置名称>)设置一个名称,3.在逻辑处理的get()方法或post() ...
- springboot+zuul(一)------实现自定义过滤器、动态路由、动态负载。
参考:https://blog.csdn.net/u014091123/article/details/75433656 https://blog.csdn.net/u013815546/articl ...
- 基于Consul+Upsync+Nginx实现动态负载均衡
基于Consul+Upsync+Nginx实现动态负载均衡 1.Consul环境搭建 下载consul_0.7.5_linux_amd64.zip到/usr/local/src目录 cd /usr/l ...
- CCNA - Part12 - 路由协议 (1) - 静态路由,动态路由 RIP
路由器 在之前关于路由器的介绍中,我们知道它是网络互联的核心设备,用于连接不同的网络,在网络之间转发 IP 数据报.对于路由器来说,路由表是其内部最为重要的构成组件.当路由器需要转发数据时,就会按照路 ...
- DedeCMS织梦动态分页类,datalist标签使用实例
<?php require_once(dirname(__FILE__)."/include/common.inc.php");//载入基础文件 require_once(D ...
- Java 动态分页类
动态分页类: Cls_page.java package pagination; public class Cls_page { private int nums;// 总条目数 private i ...
- 基于Bootstrap的Asp.net Mvc 分页
基于Bootstrap的Asp.net Mvc 分页的实现 最近写了一个mvc 的 分页,样式是基于 bootstrap 的 ,提供查询条件,不过可以自己写样式根据个人的喜好,以此分享一下.首先新建一 ...
- LayUI分页,LayUI动态分页,LayUI laypage分页,LayUI laypage刷新当前页
LayUI分页,LayUI动态分页,LayUI laypage分页,LayUI laypage刷新当前页 >>>>>>>>>>>> ...
随机推荐
- 金融量化分析【day112】:量化交易策略基本框架
摘要 策略编写的基本框架及其实现 回测的含义及其实现 初步学习解决代码错误 周期循环的开始时间 自测与自学 通过前文对量化交易有了一个基本认识之后,我们开始学习做量化交易.毕竟就像学游泳,有些东西讲是 ...
- C#开发Windows服务详细流程
1.Windows服务简单介绍 Windows服务程序是在Windows操作系统下能完成特定功能的可执行的应用程序,主要用于长时间运行的功能或者执行定时任务.一般情况下,用户不能通过用户界面来安装和启 ...
- Netty 源码分析
https://segmentfault.com/a/1190000007282628 netty社区-简书闪电侠 :https://netty.io/wiki/related-articles.ht ...
- MSSQL Server2012备份所有数据库到网络共享盘上面,并自动删除几天前的备份。。
--要备份到哪一服务的IP网络位置,要提前打开文件夹共享.这里还要输入用户名和密码,下面这一行是建立共享 exec master..xp_cmdshell 'net use \\192.168.8.1 ...
- fedora make: gcc:命令未找到(解决方法)
安装C开发环境 由于gcc包需要依赖binutils和cpp包,另外make包也是在编译中常用的,所以一共需要9个包来完成安装,因此我们只需要执行9条指令即可: yum install cpp yum ...
- 第九节:从源码的角度分析MVC中的一些特性及其用法
一. 前世今生 乍眼一看,该标题写的有点煽情,最近也是在不断反思,怎么能把博客写好,让人能读下去,通俗易懂,深入浅出. 接下来几个章节都是围绕框架本身提供特性展开,有MVC程序集提供的,也有其它程序集 ...
- Moving Average
移动平均算法Demo #!/usr/bin/python2.7 # Fetch data from BD and analyse. import json import urllib import t ...
- python学习03
字符串的基本使用 1.字符编码集 ASCII编码:外国人常用的大小写英文字母.数字和一些符号,一共127个字符,用1个字节(byte)可以涵盖完,也就是8个位,它将序列中的每个字节理解为一个字符. U ...
- java8 按条件过滤集合
//黄色部分为过滤条件list.stream().filter(user-> user.getId() > 5 && "1组".equals(user. ...
- Git使用七:修改最后一次提交、删除文件和重命名文件
修改最后一次提交: 在实际开发中,可能会遇到以下两种情景:情景一:版本刚一提交(commit)到仓库,突然想起漏掉两个文件还没有添加(add).情景二:版本刚一提交(commit)到仓库,突然想起版本 ...