web框架详解之tornado 三 url和分页
一、代码目录构建
controllers :处理业务逻辑的
account:处理账户相关的
上面目录作用和内容
controllers 包 :处理业务逻辑的
account:处理账户相关的
home是主页内容文件
settings 包:内容设置等
Setting:配置文件
statics 包: 静态文件的下相关目录
views 包: HTML文件包
内容分别为:
#/usr/bin/env python
#-*-coding:utf- -*-
import tornado.web class LoginHandler(tornado.web.RequestHandler):
def get(self,*args,**kwargs):
self.write("ok")
class LogoutHandler(tornado.web.RequestHandler):
def get(self, *args, **kwargs):
self.write("ok")
class RegisterHandler(tornado.web.RedirectHandler):
def get(self,*args,**kwargs):
self.write("ok")
account文件
#/usr/bin/env python
#-*-coding:utf--*-
import tornado.web class IndexHandler(tornado.web.RequestHandler):
def get(self, *args, **kwargs):
# self.write("index.html")
self.render("index.html")
home文件
#/usr/bin/env python
#-*-coding:utf--*- settings={
"template_path":"views",#模板路径的配置
"static_path":"statics" #静态文件
}
Setting文件
#/bin/usr/env python
#-*- coding:utf- -*-
import tornado.ioloop
import tornado.web
from controllers import home
from settings import Setting #路由映射,路由系统
application=tornado.web.Application(
[(r"/index",home.IndexHandler),],
**Setting.settings
) if __name__=="__main__":
application.listen()
tornado.ioloop.IOLoop.instance().start()
start文件
其实就是把tornado拆解了
#!/usr/bin/env python
# -*- coding:utf- -*- # 首先导入模块
import tornado.ioloop
import tornado.web
# 让这个类继承 执行
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.render("s1.html")
# 路由映射,也可以叫做路由系统
application = tornado.web.Application([
(r"/index", MainHandler),
])
if __name__ == "__main__":
application.listen()
tornado.ioloop.IOLoop.instance().start()
二、基于正则的动态路由
设置分页:在路由系统中,用正则匹配数字,并且让第一个明明为num,第二个为nid
#路由映射,路由系统
application=tornado.web.Application(
[(r"/index/(?P<num>\d*)/(?P<nid>\d*)",home.IndexHandler),],
**Setting.settings
)
#/usr/bin/env python
#-*-coding:utf--*-
import tornado.web class IndexHandler(tornado.web.RequestHandler):
def get(self,nid,num):
# self.write("index.html")
print(nid,num)
self.render("index.html")
在home文件中设置
在网页url中输入http://127.0.0.1:8000/index/12321/151
在后台中输出 151 和12321
三、路由系统之二级域名
application.add_handlers("www.cnblogs.com",[
(r"/index/(?P<page>\d*)",这里是自己定义的类)
])
二级路由就是:首先匹配域名,然后再匹配域名下的各个页面
一级路由是直接匹配各个页面
四、自定义分页:
redirect_to实现的是action方法的跳转,向浏览器发起一个新的请求,具体使用方法如下 注意点:用户连接tornado的时候,这个框架会用get方法给服务端发送页面信息,然后客户端向服务端发送消息,这里是用post方式,从客户端发送消息到服务端
#/bin/usr/env python
#-*- coding:utf- -*-
import tornado.ioloop
import tornado.web
from controllers import home
from settings import Setting #路由映射,路由系统
application=tornado.web.Application(
[(r"/index/(?P<page>\d*)",home.IndexHandler),],
**Setting.settings
) if __name__=="__main__":
application.listen()
tornado.ioloop.IOLoop.instance().start()
start代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<h1>提交数据</h1>
<form method="post" action="/index/1">
<input name="username" type="text"/>
<input name="email" type="text"/>
<input type="submit" value="提交"/>
</form>
<h1>显示数据</h1>
<table border="">
<thead>
<tr>
<th>用户名</th>
<th>邮箱</th>
</tr>
</thead>
<tbody>
{% for line in list_info %}
<tr>
<td>{{line['username']}}</td>
<td>{{line['email']}}</td>
</tr>
{% end %}
</tbody>
</table>
</body>
</html>
HTML代码
#/usr/bin/env python
#-*-coding:utf--*-
import tornado.web LIST_INFO=[
{"username":"aa","email":"pyrene3110436742@162.com"}
]
class IndexHandler(tornado.web.RequestHandler):
def get(self,page):
#假如每页显示5条数据
# page是当前页
# 第一页:: LIST_INFO[:]
#第二页:: LIST_INFO[:]
try:
page=int(page)
except Exception:
page=
if page<:
page=
start=(page-)*
end=page*
current_list=LIST_INFO[start:end] # print(nid,num)
self.render("home/index.html" ,list_info=current_list)
def post(self, *args, **kwargs):
user=self.get_argument("username")
email=self.get_argument("email")
temp={"username":user,"email":email}
LIST_INFO.append(temp)
self.redirect("/index/1")
home代码
分析:
这里有两种内容
1、用户通过表格form提交数据,通过post方法,把输入的内容添加到LIST_INFO列表中,并且通过redirect方法跳转到get方法中返回给客户端
2、内部做了页面判断,并且让页面只显示5条数据,用户通过路由系统输入url来访问每一页
自定义分页优化
通过传值来记住当前页
三中的bug问题点在于:页面输入的时候,会跳转到首页,要解决
#/usr/bin/env python
#-*-coding:utf--*-
import tornado.web LIST_INFO=[
{"username":"aa","email":"pyrene3110436742@162.com"}
]
class IndexHandler(tornado.web.RequestHandler):
def get(self,page):
#假如每页显示5条数据
# page是当前页
# 第一页:: LIST_INFO[:]
#第二页:: LIST_INFO[:]
try:
page=int(page)
except Exception:
page=
if page<:
page=
start=(page-)*
end=page*
current_list=LIST_INFO[start:end] # print(nid,num)
self.render("home/index.html" ,list_info=current_list,current_page=page)
def post(self,page):
user=self.get_argument("username")
email=self.get_argument("email")
temp={"username":user,"email":email}
LIST_INFO.append(temp)
self.redirect("/index/"+page)
home代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</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="">
<thead>
<tr>
<th>用户名</th>
<th>邮箱</th>
</tr>
</thead>
<tbody>
{% for line in list_info %}
<tr>
<td>{{line['username']}}</td>
<td>{{line['email']}}</td>
</tr>
{% end %}
</tbody>
</table>
</body>
</html>
index代码
后台get方法中自定义页码变量,传入到html中,之后用户输入触发post方法,然后在post方法中跳转到当前页面
自定义分页二:实现下图中的分页
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
.pager a{
display: inline-block;
padding: 5px;
margin: 3px;
background-color: cadetblue;
}
.pager a.active{
background-color:brown ;
color: white;
}
</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="">
<thead>
<tr>
<th>用户名</th>
<th>邮箱</th>
</tr>
</thead>
<tbody>
{% for line in list_info %}
<tr>
<!--<td>{{line['username']}}</td>-->
<td>{% raw line['username']%}</td>
<td>{{line['email']}}</td>
</tr>
{% end %}
</tbody>
</table>
<div class="pager">
{% raw str_page %}
</div>
</body>
</html>
HTML代码
#/usr/bin/env python
#-*-coding:utf--*-
import tornado.web LIST_INFO=[
{"username":"aa","email":"pyrene3110436742@162.com"}
]
for i in range():
temp={"username":"bb"+str(i),"email":str(i)+""}
LIST_INFO.append(temp)
class IndexHandler(tornado.web.RequestHandler):
def get(self,page):
#假如每页显示5条数据
# page是当前页
# 第一页:: LIST_INFO[:]
#第二页:: LIST_INFO[:]
try:
page=int(page)
except Exception:
page=
if page<:
page=
start=(page-)*
end=page*
current_list=LIST_INFO[start:end] all_pager,c=divmod(len(LIST_INFO),)
if c>:
all_pager+= list_page=[] for p in range(all_pager):
# 设置当前页的样式
if p+ ==page:
temp='<a class="active" href="/index/%s">%s</a>' %(p+,p+)
else:
temp='<a href="/index/%s">%s</a>'%(p+,p+)
list_page.append(temp) str_page="".join(list_page) # print(nid,num)
self.render("home/index.html" ,list_info=current_list,current_page=page,str_page=str_page)
python代码
实现步骤:
首先在后台计算出数据的总页数,用divemode的方法
all_pager,c=divmod(len(LIST_INFO),)
if c>:
all_pager+=
all_pager为整数,c为小数,这里判断,如果c为小数的时候让整数加上1,也就是需要显示的页数
、创建一个空列表,并且遍历计算出来的页数,返回给前端页面
list_page=[] for p in range(all_pager):
# 设置当前页的样式
if p+ ==page:
temp='<a class="active" href="/index/%s">%s</a>' %(p+,p+)
else:
temp='<a href="/index/%s">%s</a>'%(p+,p+)
list_page.append(temp) str_page="".join(list_page) # print(nid,num)
self.render("home/index.html" ,list_info=current_list,current_page=page,str_page=str_page)
注意点:
、这里要设置点击到那一页的时候就显示那一页的样式,用于区分
、由于要传给前台的是字符串,所以这里要用join方法分割成字符串
、pag参数为当前页码 前台代码:
<div class="pager">
{% raw str_page %}
</div>
由于后台传过来的数据,要按照后台的样式展示给用户,所以这里要用原声的js显示
这里注意,后台要显示的原生的js必须是指定范围的,不然会被攻击
自定义分页优化
优化如下:
具体思想如下: all_pager:总页数
current_pager:当前页
# range(当前页-,当前页++)
当 总页数<11的时候
、 显示总页数
当 总页数>11的时候
如果当前页<=:
显示前11页
如果当前页>:
如果:当前页+ >总页数:
总页数 - , 总页数
else:
当前页-, 当前页+
#s t 分页逻辑,这里让其显示11条信息
if all_pager<:
s=
t=all_pager
else:
if page<=:
s=
t=
else:
if(page+)>all_pager:
s=all_pager-
t=all_pager
else:
s=page-
t=page+ #注意这里的p代表的是s和t+1之间的页码
for p in range(s,t+):
# 设置当前页的样式
if p ==page:
temp='<a class="active" href="/index/%s">%s</a>' %(p,p)
else:
temp='<a href="/index/%s">%s</a>'%(p,p)
list_page.append(temp) str_page="".join(list_page)
python代码实现
如何做成插件?
把各个方法分别封装到类中,然后如果以后想用这个插件,直接导入这个插件中的类就可以 如果要封装页码:需要思考需求和产出什么
需求:总页数、当前页
产出:start end str_page 把方法封装到类中,类中分别对应方法
#/usr/bin/env python
#-*-coding:utf--*-
import tornado.web LIST_INFO=[
{"username":"aa","email":"pyrene3110436742@162.com"}
]
for i in range():
temp={"username":"bb"+str(i),"email":str(i)+""}
LIST_INFO.append(temp) class Pagination:
#下面封装的参数分别为,当前页数,和总的数据
def __init__(self,current_page,all_item): #初始化当前页和总页数
all_pager,c=divmod(all_item,) #all_pager为计算的到的总页数,要经过下面的判断
if c>:
all_pager+=
self.all_pager=all_pager try: #为当前页处理异常
current_page=int(current_page)
except Exception:
current_page=
if current_page<:
current_page=
self.current_page=current_page # 加上这样的装饰器,会使下面调用这个方法的时候以访问字段的形式来访问,也就是不用加上括号
@property
def start(self): #当前页的起始数据
return (self.current_page-)*
@property
def end(self): #当前页的结尾数据
return self.current_page* def page_str(self,base_url): # 生成页码逻辑
list_page=[]
if self.all_pager<:
s=
t=self.all_pager
else:
if self.current_page<=:
s=
t=
else:
if( self.current_page+)>self.all_pager:
s=self. current_page-
t=self. current_page
else:
s= self.current_page-
t= self.current_page+
for p in range(s,t+):
if p == self.current_page:
temp='<a class="active" href="%s%s">%s</a>' %(base_url,p,p) #这里设置自定义url
else:
temp='<a href="%s%s">%s</a>'%(base_url,p,p)
list_page.append(temp) return "".join(list_page) #直接返回值 class IndexHandler(tornado.web.RequestHandler):
def get(self,page): page_obj=Pagination(page,len(LIST_INFO)) #传入当前页和总页数生成对象
current_list=LIST_INFO[page_obj.start:page_obj.end] #以字段的方式来应用类中的方法
str_page=page_obj.page_str("/index/") #传入自己自定义的url # 传入参数,当前页的参数和页码数的参数
self.render("home/index.html" ,list_info=current_list,current_page=page_obj.current_page,str_page=str_page) def post(self,page):
user=self.get_argument("username")
email=self.get_argument("email")
temp={"username":user,"email":email}
LIST_INFO.append(temp)
self.redirect("/index/"+page)
python代码
跳转页面
location.href=”url”
首页:尾页:上一页:下一页都不难 搜索跳转的代码形式:
只要执行上面的就会自动跳转到指定的url
所以这里用了js的事件方法,只不过把js变成字符串的形式传递给前台,然后转化为js代码的形式
#首页
first_page='<a href="%s1">首页</a>'%(base_url,)
list_page.append(first_page) #上一页 current_page- 在javascript中加上javascript:void()表示什么也不做
if self.current_page==:
pre_page='<a href="javascript:void(0)">上一页</a>'
else:
pre_page='<a href="%s%s">上一页</a>'%(base_url,self.current_page-)
list_page.append(pre_page) #中间页数
for p in range(s,t+):
if p == self.current_page:
temp='<a class="active" href="%s%s">%s</a>' %(base_url,p,p) #这里设置自定义url
else:
temp='<a class-"active" href="%s%s">%s</a>'%(base_url,p,p)
list_page.append(temp)
#尾页
last_page='<a href=%s%s>尾页</a>'%(base_url,self.all_pager)
list_page.append(last_page) #下一页 current_page+ 在javascript中加上javascript:void()表示什么也不做
if self.current_page>=self.all_pager:
next_page='<a href="javascript:void(0)">下一页</a>'
else:
next_page='<a href="%s%s">下一页</a>'%(base_url,self.current_page+)
list_page.append(next_page) #跳转页面
jump='''<input type="text" /><a onclick="jump('%s',this);">GO</a>'''%(base_url,)
script='''<script>
function jump(baseUrl,ths){
var val=ths.previousElementSibling.value;
if(val.trim().length>){
location.href=baseUrl+val
}
}
</script>'''
list_page.append(jump)
list_page.append(script)
return "".join(list_page)
五、安全XSS攻击
xss跨站脚本攻击
<h1>显示数据</h1>
<table border="">
<thead>
<tr>
<th>用户名</th>
<th>邮箱</th>
</tr>
</thead>
<tbody>
{% for line in list_info %}
<tr>
<!--<td>{{line['username']}}</td>-->
<td>{% raw line['username']%}</td>
<td>{{line['email']}}</td>
</tr>
{% end %}
</tbody>
</table>
上面13行的就是以原始方式展示,没做处理,那么无论用户还是后台输入的js代码都会以js形式展示给用户
这种就是xss跨站脚本攻击模式
web框架详解之tornado 三 url和分页的更多相关文章
- web框架详解之tornado 一 模板语言以及框架本质
一.概要 Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本.这个 Web 框架看起来有些像web.py 或者 Google 的 webapp,不过 ...
- web框架详解之 tornado 四 模板引擎、session、验证码、xss
一.模板引擎 基本使用 继承,extends 页面整体布局用继承 导入,include 如果是小组件等重复的那么就用导入 下面是目录 首先在controllers里面创建一个文件,文件里面是页面类 # ...
- web框架详解之tornado 二 cookie
一.tornado之cookie一 目录: <!DOCTYPE html> <html lang="en"> <head> <meta c ...
- Spark2.1.0——内置Web框架详解
Spark2.1.0——内置Web框架详解 任何系统都需要提供监控功能,否则在运行期间发生一些异常时,我们将会束手无策.也许有人说,可以增加日志来解决这个问题.日志只能解决你的程序逻辑在运行期的监控, ...
- web框架详解之三Modal
一.Modal操作之创建表,添加数据 1. 配置Django中settings的设置连接mysql数据库,然后在mysql数据库中创建库 2. 在models中创建表.继承Model 3. 在sett ...
- (转) shiro权限框架详解06-shiro与web项目整合(上)
http://blog.csdn.net/facekbook/article/details/54947730 shiro和web项目整合,实现类似真实项目的应用 本文中使用的项目架构是springM ...
- JAVA Eclipse使用Maven构建web项目详解(SSM框架)
tips: 启动项目后,welcome-file的链接即为测试用例 部署maven web项目 Eclipse使用Maven构建web项目详解 pom.xml添加webapp依赖: <depen ...
- jQuery Validate验证框架详解
转自:http://www.cnblogs.com/linjiqin/p/3431835.html jQuery校验官网地址:http://bassistance.de/jquery-plugins/ ...
- 【转】jQuery Validate验证框架详解
jQuery校验官网地址:http://bassistance.de/jquery-plugins/jquery-plugin-validation 一.导入js库 <script type=& ...
随机推荐
- Java中的split函数的用法
Java中的 split 函数是用于按指定字符(串)或正则去分割某个字符串,结果以字符串数组形式返回: 例如: String str="1234@abc"; String[] a ...
- java严格验证日期是否正确的代码
package com.xxxx.util; /** * 输入日期 并进行验证格式是否正确 */ public class FDate { public static void main(String ...
- NFS详细分析
1. NFS服务介绍 1.1什么是NFS服务 NFS(Network File System)即网络文件系统,它允许网络中的计算机之间通过TCP/IP网络共享资源.在NFS的应用中,本地NFS的客户端 ...
- centos中git使用
先用root用户登录, yum install git 进行安装,然后退出用普通用户登录. ssh-keygen -t rsa -C "tuhooo@163.com" 登录GitH ...
- Hibernate: 数据持久层框架
Hibernate 是一种Java语言下的对象关系映射解决方案. 它是使用GNU宽通用公共许可证发行的自由.开源的软件.它为面向对象的领域模型到传统的关系型数据库的映射,提供了一个使用方便的框架.Hi ...
- android 小游戏之数字猜猜
http://www.cnblogs.com/whatbeg/p/4152333.html
- 关于reset.css的那些事
分析过程:body: 发现在没有填写任何内容的情况下是没有margin 的 只有在加入了文字或者div中以后才有了margin(废话)那么 我想问一下 body的padding 默认的有吗??在哪里 ...
- web安全之SQL注入---第二章 什么是sql注入?
如何理解SQL注入?SQL注入是一种将SQL代码添加到输入参数中传递到SQL服务器解析并执行的一种攻击方法总结:其实就是输入的参数没有进行过滤,直接参加sql语句的运算,达到不可预想的结果.SQL注入 ...
- BZOJ 1602 [Usaco2008 Oct]牧场行走 dfs
题意:id=1602">链接 方法:深搜暴力 解析: 这题刚看完还有点意思,没看范围前想了想树形DP,只是随便画个图看出来是没法DP的,所以去看范围. woc我没看错范围?果断n^2暴 ...
- Android Studio 中 Gradle 依赖的统一管理(rootProjectt)
最近遇到Android Studio 中 Gradle 依赖的统一管理的不懂得地方,看大神的也没看懂,百度了一下,使用起来还挺方便 下面是链接,在这里我就不详细说明了, http://www.jian ...