web 框架3 tornado 分页 session 继承extend 包含include 路由系统的域名使用 钩子函数
1 路由系统正则匹配,浏览器输入数字
application = tornado.web.Application([ (r"/index/(?P<page>\d*)",home.IndexHandler), ],**settings)
访问时候 地址最后要么是数字结尾要么是index/结尾, / 不要忘记
127.0.0.1:(start.py内的port)/index/1 或者 127.0.0.1:(start.py内的port)/index/ 因为后面有规则匹配
1.1 目录结构
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = 'liujianzuo' import tornado.ioloop import tornado.web from controller import home settings = { "template_path" : "views", # 模板路径的配置 "static_path" : "statics", } #路由映射 路由系统 application = tornado.web.Application([ (r"/index/(?P<page>\d*)",home.IndexHandler), ],**settings) if __name__ == '__main__': # socket 运行起来 application.listen(8888) tornado.ioloop.IOLoop.instance().start()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>首页</title> </head> <body> <div>首页</div> <h2>提交数据</h2> <form method="post" action="/index/{{all_ye}}"> <input type="text" name="username"> <input type="text" name="email"> <input type="submit"> </form> <h2>显示数据</h2> <table border="1px"> <thead> <tr> <th>用户名</th> <th>邮箱地址</th> </tr> </thead> <tbody> {% for item in info_list %} <tr> <td>{{ item["username"] }}</td> <td>{{ item["email"] }}</td> </tr> {% end %} </tbody> </table> <div> <a>上一页</a> {% for i in all_page %} <a href="/index/{{ i }}">{{ i }}</a> {% end %} <a>下一页</a> </div> </body> </html>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = 'liujianzuo' #!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = 'liujianzuo' import tornado.ioloop import tornado.web INFO_LIST = [ {"username":"alex","email":"alex3721@163.com"} ] class IndexHandler(tornado.web.RequestHandler): def get(self, page): try: page = int(page) except Exception as e: page = 1 if page < 1: page = 1 all_num = INFO_LIST.__len__() x = divmod(all_num,5) all_page = x[0] if x[1] == 0 else x[0]+1 print(all_page) all = [] for i in range(all_page): all.append(i+1) print(all) start = (page - 1)*5 end = page * 5 CURRENT_LIST = INFO_LIST[start:end] print(CURRENT_LIST) self.render("home/index.html",info_list = CURRENT_LIST,all_page =all,all_ye=all_page) def post(self, page): username = self.get_argument("username",None) email = self.get_argument("email",None) temp = {"username":username,"email":email} INFO_LIST.append(temp) self.redirect("/index/"+page)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = 'liujianzuo' #!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = 'liujianzuo' import tornado.ioloop import tornado.web class RegisterHandler(tornado.web.RequestHandler): def get(self, *args, **kwargs): pass class LogoutHandler(tornado.web.RequestHandler): def get(self, *args, **kwargs): pass class LoginHandler(tornado.web.RequestHandler): def get(self, *args, **kwargs): pass def post(self, *args, **kwargs): pass
2 分页为整合前 目录结构和代码
访问地址 :127.0.0.1:(start.py内的port)/index/1
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = 'liujianzuo' import tornado.ioloop import tornado.web from controller import home settings = { "template_path" : "views", # 模板路径的配置 "static_path" : "statics", } #路由映射 路由系统 application = tornado.web.Application([ (r"/index/(?P<page>\d*)",home.IndexHandler), ],**settings) if __name__ == '__main__': # socket 运行起来 application.listen(8880) tornado.ioloop.IOLoop.instance().start()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>首页</title> <style> .pager a{ display: inline-block; padding: 5px; margin: 3px; background-color: #e0e0e0; border: 1px solid red; border-radius: 6px; } .pager a.active{ background-color: red; color: white; } </style> </head> <body> <div>首页</div> <h2>提交数据</h2> <form method="post" action="/index/{{all_ye}}"> <input type="text" name="username"> <input type="text" name="email"> <input type="submit"> </form> <h2>显示数据</h2> <table border="1px"> <thead> <tr> <th>用户名</th> <th>邮箱地址</th> </tr> </thead> <tbody> {% for item in info_list %} <tr> <td>{{ item["username"] }}</td> <td>{{ item["email"] }}</td> </tr> {% end %} </tbody> </table> <div class="pager"> {% raw str_page %} </div> </body> </html>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = 'liujianzuo' #!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = 'liujianzuo' import tornado.ioloop import tornado.web INFO_LIST = [ {"username":"alex","email":"alex3721@163.com"} ] for i in range(300): temp = {"username":"alex"+str(i),"email":str(i)+"alex3721@163.com"} INFO_LIST.append(temp) class IndexHandler(tornado.web.RequestHandler): def get(self, page): try: page = int(page) except Exception as e: page = 1 if page < 1: page = 1 start = (page - 1)*5 end = page * 5 CURRENT_LIST = INFO_LIST[start:end] print(CURRENT_LIST) all_pager,c = divmod(len(INFO_LIST),5) if c > 0: all_pager +=1 list_page = [] if all_pager < 11: s =1 t = all_pager +1 else: if page<6: s = 1 t = 12 else: if all_pager - page >5: s = page -5 t = page +5 else: s = all_pager - 5 t = all_pager +1 # 上一页 if page == 1: prev = "<a href='javascript:void(0);'> 上一页</a>" else: prev = "<a href='/index/%s'> 上一页</a>" % (page -1) list_page.append(prev) 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) # 下一页 if page == all_pager: nex = "<a href='javascript:void(0);'> 下一页</a>" else: nex = "<a href='/index/%s'>下一页</a>" % (page + 1) list_page.append(nex) str_page = "".join(list_page) self.render("home/index.html",info_list = CURRENT_LIST,all_page =all,str_page=str_page,all_ye=all_pager) def post(self, page): username = self.get_argument("username",None) email = self.get_argument("email",None) temp = {"username":username,"email":email} INFO_LIST.append(temp) self.redirect("/index/"+page)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = 'liujianzuo' #!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = 'liujianzuo' import tornado.ioloop import tornado.web class RegisterHandler(tornado.web.RequestHandler): def get(self, *args, **kwargs): pass class LogoutHandler(tornado.web.RequestHandler): def get(self, *args, **kwargs): pass class LoginHandler(tornado.web.RequestHandler): def get(self, *args, **kwargs): pass def post(self, *args, **kwargs): pass
2 分页为整合后 目录结构和代码 说明
访问地址 :127.0.0.1:(start.py内的port)/index/1
common 下的pager模块
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = 'liujianzuo' class Pagenation: def __init__(self, current_page,all_item,base_url,per_items): """ :param current_page: 当前页 :param all_item: 所有数据总条数 :param base_url: 提交url 例如 /index/ :param per_items: 每页显示内容条数 """ try: page = int(current_page) except Exception as e: page = 1 if page < 1: page = 1 all_pager , c = divmod(all_item,per_items) if c >0: all_pager += 1 self.current_page = page self.all_pager = all_pager self.base_url = base_url self.per_items = per_items @property def start(self): return (self.current_page -1 )* self.per_items @property def end(self): return self.current_page * self.per_items def string_pager(self): list_page = [ ] if self.all_pager <11: s = 1 t = self.all_pager + 1 else: if self.current_page < 6: s = 1 t = 12; else: if (self.current_page + self.per_items ) <self.all_pager: s = self.current_page - 5 t = self.current_page+5 + 1 else: s = self.all_pager - 10 t = self.all_pager +1 # 首页 first = "<a href='/index/1'>首页</a>" list_page.append(first) if self.current_page == 1: prev = "<a href='javascript:void(0);'> 上一页</a>" else: prev = "<a href='/index/%s'> 上一页</a>" % (self.current_page - 1) list_page.append(prev) for p in range(s, t): if p == self.current_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) # 下一页 if self.current_page == self.all_pager: nex = "<a href='javascript:void(0);'> 下一页</a>" else: nex = "<a href='/index/%s'>下一页</a>" % (self.current_page + 1) list_page.append(nex) # 尾页 first = "<a href='/index/%s'>首页</a>" % (self.all_pager) list_page.append(first) # 跳转 jump = """<input type='text' /><a onclick="Jump('%s',this);">GO</a>""" % ('/index/') script = """<script> function Jump(baseUrl,ths){ var val = ths.previousElementSibling.value; if(val.trim().length>0){ location.href = baseUrl + val; } } </script>""" list_page.append(jump) list_page.append(script) str_page = "".join(list_page) return str_page
controller home文件的调用pager模块
from commons import pager # 写在前端的文涨以字典格式存放测试 INFO_LIST = [ {"username":"alex","email":"alex3721@163.com"} ] #创建300条文章来进行测试分页 for i in range(300): temp = {"username":"alex"+str(i),"email":str(i)+"alex3721@163.com"} INFO_LIST.append(temp) class IndexHandler(tornado.web.RequestHandler): def get(self, page): obj = pager.Pagenation(page,len(INFO_LIST),"/index/",10) current_list = INFO_LIST[obj.start:obj.end] str_page = obj.string_pager() self.render("home/index.html",info_list = current_list,all_page =all,str_page=str_page,all_ye=obj.all_pager)
测试目录结构的所有代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = 'liujianzuo' import tornado.ioloop import tornado.web from controller import home settings = { "template_path" : "views", # 模板路径的配置 "static_path" : "statics", } #路由映射 路由系统 application = tornado.web.Application([ (r"/index/(?P<page>\d*)",home.IndexHandler), ],**settings) if __name__ == '__main__': # socket 运行起来 application.listen(8880) tornado.ioloop.IOLoop.instance().start()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>首页</title> <style> .pager a{ display: inline-block; padding: 5px; margin: 3px; background-color: #e0e0e0; border: 1px solid red; border-radius: 6px; } .pager a.active{ background-color: red; color: white; } </style> </head> <body> <div>首页</div> <h2>提交数据</h2> <form method="post" action="/index/{{all_ye}}"> <input type="text" name="username"> <input type="text" name="email"> <input type="submit"> </form> <h2>显示数据</h2> <table border="1px"> <thead> <tr> <th>用户名</th> <th>邮箱地址</th> </tr> </thead> <tbody> {% for item in info_list %} <tr> <td>{{ item["username"] }}</td> <td>{{ item["email"] }}</td> </tr> {% end %} </tbody> </table> <div class="pager"> {% raw str_page %} </div> </body> </html>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = 'liujianzuo' #!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = 'liujianzuo' import tornado.ioloop import tornado.web class RegisterHandler(tornado.web.RequestHandler): def get(self, *args, **kwargs): pass class LogoutHandler(tornado.web.RequestHandler): def get(self, *args, **kwargs): pass class LoginHandler(tornado.web.RequestHandler): def get(self, *args, **kwargs): pass def post(self, *args, **kwargs): pass
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = 'liujianzuo' #!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = 'liujianzuo' import tornado.ioloop import tornado.web from commons import pager INFO_LIST = [ {"username":"alex","email":"alex3721@163.com"} ] for i in range(300): temp = {"username":"alex"+str(i),"email":str(i)+"alex3721@163.com"} INFO_LIST.append(temp) class IndexHandler(tornado.web.RequestHandler): def get(self, page): obj = pager.Pagenation(page,len(INFO_LIST),"/index/",10) current_list = INFO_LIST[obj.start:obj.end] str_page = obj.string_pager() self.render("home/index.html",info_list = current_list,all_page =all,str_page=str_page,all_ye=obj.all_pager) def post(self, page): username = self.get_argument("username",None) email = self.get_argument("email",None) temp = {"username":username,"email":email} INFO_LIST.append(temp) self.redirect("/index/"+page)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = 'liujianzuo' class Pagenation: def __init__(self, current_page,all_item,base_url,per_items): """ :param current_page: 当前页 :param all_item: 所有数据总条数 :param base_url: 提交url 例如 /index/ :param per_items: 每页显示内容条数 """ try: page = int(current_page) except Exception as e: page = 1 if page < 1: page = 1 all_pager , c = divmod(all_item,per_items) if c >0: all_pager += 1 self.current_page = page self.all_pager = all_pager self.base_url = base_url self.per_items = per_items @property def start(self): return (self.current_page -1 )* self.per_items @property def end(self): return self.current_page * self.per_items def string_pager(self): list_page = [ ] if self.all_pager <11: s = 1 t = self.all_pager + 1 else: if self.current_page < 6: s = 1 t = 12; else: if (self.current_page + self.per_items ) <self.all_pager: s = self.current_page - 5 t = self.current_page+5 + 1 else: s = self.all_pager - 10 t = self.all_pager +1 # 首页 first = "<a href='/index/1'>首页</a>" list_page.append(first) if self.current_page == 1: prev = "<a href='javascript:void(0);'> 上一页</a>" else: prev = "<a href='/index/%s'> 上一页</a>" % (self.current_page - 1) list_page.append(prev) for p in range(s, t): if p == self.current_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) # 下一页 if self.current_page == self.all_pager: nex = "<a href='javascript:void(0);'> 下一页</a>" else: nex = "<a href='/index/%s'>下一页</a>" % (self.current_page + 1) list_page.append(nex) # 尾页 first = "<a href='/index/%s'>首页</a>" % (self.all_pager) list_page.append(first) # 跳转 jump = """<input type='text' /><a onclick="Jump('%s',this);">GO</a>""" % ('/index/') script = """<script> function Jump(baseUrl,ths){ var val = ths.previousElementSibling.value; if(val.trim().length>0){ location.href = baseUrl + val; } } </script>""" list_page.append(jump) list_page.append(script) str_page = "".join(list_page) return str_page
3 继承extend 与 引用include
说明:
1 extend 继承
master是公共母版,其他是继承者
母版格式: 需要子板继承的格式都写在母版,各自子板的格式自己写
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>母版</title> <style> .pg-header{ height: 49px; background-color: black; } .pg-footer{ height: 100px; background-color: #dddddd; } </style> {% block css %} {% end %} </head> <body> <div class="pg-header"> 母版 header </div> <div class="pg-content"> {% block body %}
{% end %} </div> <div class="pg-footer"> 母版 footer</div> {% block js %} {% end %} </body> </html>
子板格式 : extend/index.html extend/fuck.html
index.html
{% extends "../master/layout.html" %} {% block body %} <h1>继承1 fuck</h1> {% include "../include/form.html" %} {% end %}
fuck.html
{% extends "../master/layout.html" %} {% block body %} <h1>继承2index</h1> {% include "../include/form.html" %} {% end %} {% block js %} <script> console.log("sd") </script> {% end %}
2 引用 include 目录结构在上面的截图
引用相对位置的页面即可 {% include "../include/form.html" %}
extend/fuck.html
{% extends "../master/layout.html" %} {% block body %} <h1>继承2index</h1> {% include "../include/form.html" %} {% end %} {% block js %} <script> console.log("sd") </script> {% end %}
include/form.html
<form> <input type="text"> <input type="submit"> </form> <ul> {% for i in list_info %} 在tornado后台get的时候传过来的一个列表,详细见上面的具体代码 <li>{{ i }}</li> {% end %} </ul>
4 tornado 路由系统的 域名处理
通过在tornado的路由配置不同的域名访问不同的index.html
测试 需要改etc/hosts文件指向127.0.0.1 buy.wupeiqi.com
域名 配置 (import 模块是拆分后的主页所在的模块)
from controller import home # 主页方法写在包下的模块 from controller import buy #路由映射 路由系统 application = tornado.web.Application([ (r"/index/(?P<page>\d*)",home.IndexHandler), ],**settings) # 域名访问 只有特定域名访问才会访问该类 application.add_handlers( "buy.wupeiqi.com$",[ (r"/index/(?P<page>\d*)",buy.IndexHandler) ] )
浏览器访问 buy.wupeiqi.com:8888/index/
5 tornado initialize钩子函数
class BaseHandler(tornado.web.RequestHandler): def initialize(self): self.session = Session(self)#将 Indexhandler 类实例化对象传入
看一下tornado.web.ReuestHandler源码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class RequestHandler(object): """Base class for HTTP request handlers. Subclasses must define at least one of the methods defined in the "Entry points" section below. """ SUPPORTED_METHODS = ("GET", "HEAD", "POST", "DELETE", "PATCH", "PUT", "OPTIONS") _template_loaders = {} # type: typing.Dict[str, template.BaseLoader] _template_loader_lock = threading.Lock() _remove_control_chars_regex = re.compile(r"[\x00-\x08\x0e-\x1f]") def __init__(self, application, request, **kwargs): super(RequestHandler, self).__init__() self.application = application self.request = request self._headers_written = False self._finished = False self._auto_finish = True self._transforms = None # will be set in _execute self._prepared_future = None self._headers = None # type: httputil.HTTPHeaders self.path_args = None self.path_kwargs = None self.ui = ObjectDict((n, self._ui_method(m)) for n, m in application.ui_methods.items()) # UIModules are available as both `modules` and `_tt_modules` in the # template namespace. Historically only `modules` was available # but could be clobbered by user additions to the namespace. # The template {% module %} directive looks in `_tt_modules` to avoid # possible conflicts. self.ui["_tt_modules"] = _UIModuleNamespace(self, application.ui_modules) self.ui["modules"] = self.ui["_tt_modules"] self.clear() self.request.connection.set_close_callback(self.on_connection_close) self.initialize(**kwargs) def initialize(self): """Hook for subclass initialization. Called for each request. A dictionary passed as the third argument of a url spec will be supplied as keyword arguments to initialize(). Example:: class ProfileHandler(RequestHandler): def initialize(self, database): self.database = database def get(self, username): ... app = Application([ (r'/user/(.*)', ProfileHandler, dict(database=database)), ]) """ pass
要想让下面的代码运行起来,还需要再下一个jQuery-cookie。js
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!/usr/bin/env python #_*_coding:utf-8_*_ import tornado.web import tornado.ioloop """ session 1、面向对象基础 面向对象中通过索引的方式访问对象,需要内部实现 __getitem__ 、__delitem__、__setitem__方法 obj = class1() obj() ====对象加括号调用的是类的__call__方法 如果要设置 获取 删除 需要__getitem__ 、__delitem__、__setitem__方法 #!/usr/bin/env python # -*- coding:utf-8 -*- class Foo(object): def __getitem__(self, key): print '__getitem__',key def __setitem__(self, key, value): print '__setitem__',key,value def __delitem__(self, key): print '__delitem__',key obj = Foo() result = obj['k1'] #obj['k2'] = 'wupeiqi' #del obj['k1'] """ container = {} # container = { # # "第一个人的随机字符串":{}, # # "第一个人的随机字符串":{'k1': 111, 'parents': '你'}, # } class Session: def __init__(self, handler): self.handler = handler self.random_str = None def __genarate_random_str(self): import hashlib import time obj = hashlib.md5() obj.update(bytes(str(time.time()), encoding='utf-8')) random_str = obj.hexdigest() return random_str # def set_value(self, key,value): def __setitem__(self, key, value): # 在container中加入随机字符串 # 定义专属于自己的数据 # 在客户端中写入随机字符串 # 判断,请求的用户是否已有随机字符串 if not self.random_str: # 重点1个: 如果我设置1成cookie的key val 这段代码一定会走,但是如果我连续对象调这个方法设置多个值,这段代码则不会走了 random_str = self.handler.get_cookie('__session__') if not random_str: random_str = self.__genarate_random_str() container[random_str] = {} else: # 客户端有随机字符串 if random_str in container.keys(): pass else: random_str = self.__genarate_random_str() container[random_str] = {} self.random_str = random_str # self.random_str = asdfasdfasdfasdf container[self.random_str][key] = value self.handler.set_cookie("__session__", self.random_str) def __getitem__(self, key): # 获取客户端的随机字符串 # 从container中获取专属于我的数据 # 专属信息【key】 random_str = self.handler.get_cookie("__session__") print("client ", random_str) if not random_str: return None # 客户端有随机字符串 user_info_dict = container.get(random_str,None) if not user_info_dict: return None value = user_info_dict.get(key, None) return value class BaseHandler(tornado.web.RequestHandler): def initialize(self): self.session = Session(self)#将 Indexhandler 类实例化对象传入 class IndexHandler(BaseHandler): def get(self): if self.get_argument("u",None) in ["alex","eric"]: self.session["is_login"] = True self.session["name"] = self.get_argument("u",None) print(container) self.write("dffff df cookie设置成功了") else: self.write("请d d s 登录") class ManaggerHandler(BaseHandler): def get(self, *args, **kwargs): print(container) # print(self.get_cookie("__session__")) val = self.session["is_login"] if val: self.write(self.session["name"]+"登录成功") else: self.write("登录失败1sdfdsfds2") # 图片验证码 class CheckCodeHandler(BaseHandler): def get(self, *args, **kwargs): #生成 图片并且返回 import io import check_code mstream = io.BytesIO() img, code = check_code.create_validate_code() # 将图片对象写入mstream, img.save(mstream,"GIF") # 为每个用户保存期验证码 self.session["CheckCode"] = code self.write(mstream.getvalue()) class LoginHandler(BaseHandler): def get(self, *args, **kwargs): self.render('login.html', status="") def post(self, *args, **kwargs): user = self.get_argument('user', None) pwd = self.get_argument('pwd', None) code = self.get_argument('code', None) check_code = self.session["CheckCode"] if code.upper() == check_code.upper(): self.write('验证码正确') else: # self.redirect('/login') self.render('login.html', status='验证码错误') # csrf class CsrfHandler(BaseHandler): def get(self, *args, **kwargs): self.render('csrf.html') def post(self, *args, **kwargs): self.write('csrf.post') settings = { "template_path":"views", "static_path":"statics", "static_url_prefix":"/statics/", "cookie_secret":"dsfsfsafsdfasdf", 'xsrf_cookies': True # csrf的cookie } application = tornado.web.Application([ (r"/index",IndexHandler), (r"/manager",ManaggerHandler), (r"/login", LoginHandler), (r"/check_code", CheckCodeHandler), (r"/csrf", CsrfHandler), # 定义路由 ],**settings) if __name__ == '__main__': application.listen(8888) tornado.ioloop.IOLoop.instance().start()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/login" method="post"> <p><input name="user" type="text" placeholder="用户"/></p> <p><input name='pwd' type="text" placeholder="密码"/></p> <p> <input name="code" type="text" placeholder="验证码"/> <img src="/check_code" onclick='ChangeCode();' id='imgCode'> </p> <input type="submit" value="Submit" /> <span style="color:red">{{status}}</span> </form> <script type="text/javascript"> function ChangeCode() { var code = document.getElementById('imgCode'); // code.src += '?'; } </script> </body> </html>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div> <h1> cookie有两种写入方式: <br> 1 服务端写入到浏览器 <br> 2 浏览器自己通过js写入 document.cookie </h1> </div> <script src="/statics/jquery.cookie.js"></script> <script src="/statics/jquery-1.12.4.js"></script> <script> // javascripts方式 在浏览器设置cookie function setCookieBySeconds(name,value,expires) { var current_date = new Date(); current_date.setDate(current_date.getSeconds() + expires); document.cookie = name + "= " +value +";expires=" + current_date.toUTCString() }; function setCookieByDays(name,value,expires) { var current_date = new Date(); current_date.setDate(current_date.getDay() + expires); document.cookie = name +"= " +value +";expires="+current_date.toUTCString() // 要转换为utc时间 } // 调用 // setCookieBySeconds('k1','v1',5) // 5秒过期 // setCookieByDays('k1','v1',5) // 5天过期 //###################jQuery设置################### $.cookie('k1','v1',{expires:7}); // 7天 设置k1=v1的cookie7天过期 //如果不是按天的话,需要先定义时间秒变量 var current_date = new Date(); current_date.setDate(current_date.getSeconds() + 6) ; //当前时间+6s $.cookie('k1',"v1",{expires:current_date}) //6s 后过期 </script> </body> </html>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/csrf" method="post"> {% raw xsrf_form_html() %} <!--输出结果如下--> <!--<input type="hidden" name="_xsrf" value="2|1a3c1c71|31ad9ca267d4350e09d426eb66244e5b|1470061982">--> <p><input name="user" type="text" placeholder="用户"/></p> <p><input name='pwd' type="text" placeholder="密码"/></p> <p> <input name="code" type="text" placeholder="验证码"/> <img src="/check_code" onclick='ChangeCode();' id='imgCode'> </p> <input type="submit" value="Submit" /> <span style="color:red"></span> </form> <script src="/statics/jquery-1.12.4.js"></script> <input type="button" value="Ajax CSRF" onclick="SubmitCsrf();" /> <script type="text/javascript"> function ChangeCode() { var code = document.getElementById('imgCode'); code.src += '?'; } function getCookie(name) { var r = document.cookie.match("\\b" + name + "=([^;]*)\\b"); return r ? r[1] : undefined; /*document.cookie "k1=2|1:0|10:1469588097|2:k1|4:OTk5|1b6ea1b4be4fa44f24e1add4447c74c27f969248bef14f19b347ed9f703b20a5; user="2|1:0|10:1469606426|4:user|8:YWxleA==|465b3e5dc3a2585bd5f5200a46c11e406b759a4c4fd7d96f5554b99bcdc619e9"; _xsrf=2|53738789|78e2075a2e9baef6409bbd132f6bd5a3|1470061982; __session__=f01a331979313ee036accf4be458ef11" name = "_xsrf" "_xsrf" document.cookie.match("\\b" + name + "=([^;]*)\\b"); ["_xsrf=2|53738789|78e2075a2e9baef6409bbd132f6bd5a3|1470061982", "2|53738789|78e2075a2e9baef6409bbd132f6bd5a3|1470061982"]*/ } function SubmitCsrf() { var nid = getCookie('_xsrf'); //csrf的name名 $.post({ url: '/csrf', data: {'k1': 'v1',"_xsrf": nid}, success: function (callback) { // Ajax请求发送成功有,自动执行 // callback,服务器write的数据 callback=“csrf.post” console.log(callback); } }); } </script> </body> </html>