【python之路44】tornado的用法 (二)
参考:https://www.cnblogs.com/sunshuhai/articles/6253815.html
一、代码目录构建
代码目录设置如下图:
#!/usr/bin/env python # -*- coding:utf-8 -*- import tornado.web class LogInHandler(tornado.web.RequestHandler): def get(self): self.write("LogIn") class LogOutHandler(tornado.web.RequestHandler): def get(self): self.write("LogOut") class RegistHandler(tornado.web.RequestHandler): def get(self): self.write("Regist")
#!/usr/bin/env python # -*- coding:utf-8 -*- import tornado.web class IndexHandler(tornado.web.RequestHandler): def get(self): self.write("Index")
#!/usr/bin/env python # -*- coding:utf-8 -*- import tornado.ioloop import tornado.web from controllers import account from controllers import home settings = { 'template_path':'views', #配置模板文件路径 'static_path':'statics', #配置静态文件路径 } #路由映射 application = tornado.web.Application([ (r"/login", account.LogInHandler), (r"/logout", account.LogOutHandler), (r"/regist", account.RegistHandler), (r"/index", home.IndexHandler) ],**settings) #**settings是让配置生效 if __name__ == "__main__": application.listen(8888) tornado.ioloop.IOLoop.instance().start()
二、基于正则的动态路由
(r"/index/(\d+)", home.IndexHandler)
class IndexHandler(tornado.web.RequestHandler):
def get(self,num):
print(num)
self.write("Index")
http://127.0.0.1:8888/index/11,用这个url访问时会打印输出:11
(r"/index/(\d+)/(\d*)", home.IndexHandler)
class IndexHandler(tornado.web.RequestHandler):
def get(self,num,page):
print(num,page)
self.write("Index")
http://127.0.0.1:8888/index/11/22,用这个url访问时会打印输出:11,22
(r"/index/(?P<page>\d+)/(?P<num>\d*)", home.IndexHandler) #?P<page>匹配到的第一个分组命名为page
class IndexHandler(tornado.web.RequestHandler):
def get(self,num,page):
print(num,page)
self.write("Index")
http://127.0.0.1:8888/index/11/22,用这个url访问时会打印输出:22,11
(三)XSS跨站脚本攻击
如下面这个html
<h1>aaaaa<h1>
<script>alert(123)</script>
这个html一旦被访问就会运行script代码,弹窗显示123
那么在一些网站中的文本框中可以输入script代码,一旦网站没有对代码做相应的处理,就会运行
tornado是做了处理的,文本框中输入代码是作为文本的,但也可以原始状态展示,这样就会运行这段代码,例如:
<td>{% raw item["email"] %}</td>
这样一旦添加数据后,代码会被执行,会直接弹窗显示123
四、分页
其中home.py中的class Page类可以直接当做插件用,可以使用在其他的web框架中
#!/usr/bin/env python # -*- coding:utf-8 -*- import tornado.web class LogInHandler(tornado.web.RequestHandler): def get(self): self.write("LogIn") class LogOutHandler(tornado.web.RequestHandler): def get(self): self.write("LogOut") class RegistHandler(tornado.web.RequestHandler): def get(self): self.write("Regist")
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>分页</title> <style> .page a{ display: inline-block; padding: 5px; margin:3px; background-color: darkseagreen; } .page a.ActivePage{ background-color: brown; color: aliceblue; } </style> </head> <body> <form method="post" action="/index/"> 用户名:<input type="text" name="username"> 邮箱:<input type="text" name="email"> <input type="submit" value="提交"> </form> <table> <thead> <tr> <th>用户名</th> <th>邮箱</th> </tr> </thead> <tbody> {% for item in list_info %} <tr> <td>{{item["username"]}}</td> <!--<td>{{item["email"]}}</td>--> <td>{% raw item["email"] %}</td> </tr> {% end %} </tbody> </table> <div class="page"> {% raw html_a %} </div> </body> </html>
#!/usr/bin/env python # -*- coding:utf-8 -*- import tornado.ioloop import tornado.web from controllers import account from controllers import home settings = { 'template_path':'views', #配置模板文件路径 'static_path':'statics', #配置静态文件路径 } #路由映射 application = tornado.web.Application([ (r"/login", account.LogInHandler), (r"/logout", account.LogOutHandler), (r"/regist", account.RegistHandler), (r"/index/(?P<page>\d*)", home.IndexHandler) ],**settings) #**settings是让配置生效 if __name__ == "__main__": application.listen(8888) tornado.ioloop.IOLoop.instance().start()
#!/usr/bin/env python # -*- coding:utf-8 -*- import tornado.web import math LIST_INFO = [] for i in range(999): LIST_INFO.append({"username":"sunshuhai" + str(i),"email": str(i) + "123.qq.com"}) class Page: #分页的内容-列表,当前页码,每页的数据条数,基础url def __init__(self,list_content,crrent_page,num_of_page,base_url): try: crrent_page = int(crrent_page) except: crrent_page = 1 if crrent_page<1: crrent_page = 1 quotient,remainder =divmod(len(list_content),num_of_page) if remainder>0: all_page=quotient+1 else: all_page =quotient self.all_page = all_page self.crrent_page = crrent_page self.num_of_page = num_of_page self.base_url = base_url @property def start(self): return (self.crrent_page - 1) * self.num_of_page @property def end(self): return self.crrent_page * self.num_of_page def crrent_page_content(self): pass def show_page_html(self): list_html=[] if self.all_page <= 11: start_page = 1 end_page = self.crrent_page else: if self.crrent_page<=6: start_page = 1 end_page = 11 else: if self.crrent_page+5 >self.all_page: start_page = self.all_page-10 end_page = self.all_page else: start_page = self.crrent_page - 5 end_page = self.crrent_page + 5 befor = '<a href="%s1">首页</a>' % (self.base_url) list_html.append(befor) if self.crrent_page-1>=1: next_page = '<a href="%s%s">上一页</a>' % (self.base_url,self.crrent_page-1) else: next_page = '<a href="javascript:void(0)">上一页</a>' list_html.append(next_page) for p in range(start_page,end_page+1): if p==self.crrent_page: list_html.append('<a class="ActivePage" href="%s%s">%s</a>' % (self.base_url,p, p)) else: list_html.append('<a href="%s%s">%s</a>' %(self.base_url,p,p)) if self.crrent_page >= self.all_page: previous_page = '<a href="javascript:void(0)">下一页</a>' else: previous_page = '<a href="%s%s">下一页</a>' % (self.base_url,self.crrent_page+1) list_html.append(previous_page) after ='<a href="%s%s">尾页</a>' %(self.base_url,self.all_page) list_html.append(after) jump = """<input type="text"><a onclick="Jump('%s',this);">GO</a>""" %(self.base_url) javasc = """ <script> function Jump(baseUrl,ths) { var val = ths.previousElementSibling.value; if(val.trim().length>0){ location.href=baseUrl + val; } } </script> """ list_html.append(jump) list_html.append(javasc) html_str = ''.join(list_html) return html_str class IndexHandler(tornado.web.RequestHandler): def get(self,page): #每5条数据分一页[0:5] [5:10] [10:15] page = Page(LIST_INFO,page,20,"/index/") list_page = LIST_INFO[page.start:page.end] html_str =page.show_page_html() self.render("index.html",list_info = list_page,html_a = html_str) def post(self, *args, **kwargs): user = self.get_argument("username") email = self.get_argument("email") temp_dict = {"username":user,"email":email} LIST_INFO.append(temp_dict) p = math.ceil(len(LIST_INFO)/5) self.redirect("/index/%s" %p)
五、路由系统之二级域名支持
1)首先配置host文件模拟域名访问
127.0.0.1 localhost
127.0.0.1 ssh.com
127.0.0.1 buy.ssh.com
2)配置路由系统
#路由映射
application = tornado.web.Application([
(r"/login", account.LogInHandler),
(r"/logout", account.LogOutHandler),
(r"/regist", account.RegistHandler),
(r"/index/(?P<page>\d*)", home.IndexHandler)
],**settings) #**settings是让配置生效
application.add_handlers('buy.ssh.com$',[
(r"/index/(?P<page>\d*)",buy.IndexHandler)
])
buy.py中的IndexHandler为:
import tornado.web
class IndexHandler(tornado.web.RequestHandler):
def get(self,page):
self.write("buy.Index")
3)用域名访问:http://buy.ssh.com:8888/index/1
结果显示:
六、模板引擎的补充用法(继承:extends,导入:include)
1)extends 继承
母版的html中可以使用占位符
<div calss="pg-content">
{% block body %}{% end %}
</div>
如果继承上面母版中有占位符的html,只需要替换占位符的位置就可以
{% extends '../master/layout.html' %}
{% block boy %}
<h1>Index</h1>
{% end %}
继承母版的优点:公共样式都可以放在母版中,个别样式继承母版后进行替换
2)include 导入
一些共用的小的组件,可以设置为共用,html如果想用只需要导入即可
下面是form.html中的共用代码:
<form action="/">
<input type="text">
<input type="submit">
</form>
使用时只需要导入即可,实际就相当于在导入的位置写了form标签的代码。
{% block body %}
<h1>Index</h1>
{% include '../include/form.html' %}
{% end %}
3)实例如下:
#!/usr/bin/env python # -*- coding:utf-8 -*- import tornado.web class IndexHandler(tornado.web.RequestHandler): def get(self,*args,**kwargs): self.render('extend/index.html',info_list=['111','222','333']) class FuckOffHandler(tornado.web.RequestHandler): def get(self,*args,**kwargs): self.render('extend/fuck.html')
{% extends '../master/layout.html' %} {% block body %} <h1>fuckoff</h1> {% end %} {% block js %} <script> cosole.log('fuckoff') </script> {% end %}
{% extends '../master/layout.html' %} {% block css %} <style> div{ border:1px solid red; } </style> {% end %} {% block body %} <h1>Index</h1> {% include '../include/form.html' %} {% end %} {% block js %} <script> cosole.log('index') </script> {% end %}
<form action="/"> <input type="text"> <input type="submit"> </form> <ul> {% for item in info_list %} <li>{{item}}</li> {% end %} </ul>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .pg-header{ height: 48px; background-color: black; } .pg-footer{ height: 100px; background-color: #dddddd; } </style> <!--block块上面是共用样式,下面是具体每个页面的自定制样式--> {% block css %}{% end %} </head> <body> <div class="pg-header"> </div> <div calss="pg-content"> {% block body %}{% end %} </div> <div class="pg-footer"> 我是页面底部 </div> <script src="xxxxj"></script> <!--block块上面是共用js,下面是具体每个页面的自定制js--> {% block js %}{% end %} </body> </html>
#!/usr/bin/env python # -*- coding:utf-8 -*- import tornado.ioloop import tornado.web from controllers import extend settings = { 'template_path':'views', #配置模板文件路径 'static_path':'statics', #配置静态文件路径 } #路由映射 application = tornado.web.Application([ (r"/index", extend.IndexHandler), (r"/fuckoff", extend.FuckOffHandler), ],**settings) #**settings是让配置生效 #二级域名的配置 # application.add_handlers('buy.ssh.com$',[ # (r"/index/(?P<page>\d*)",buy.IndexHandler) # ]) if __name__ == "__main__": application.listen(8888) tornado.ioloop.IOLoop.instance().start()