Python 框架- Tornado
Tornado 是可扩展的非阻塞式WEB服务器及其相关工具的开源版本。 Tornado 和想在的主流web服务器框架区别:它是非阻塞式服务器,而且速度相当快。得力于非阻塞式方式和对epoll的运用。tornado 每秒可以处理千计的连接。
一:安装
1 pip install tornado 2 源码安装:https://pypi.python.org/packages/source/t/tornado/tornado-4.3.tar.gz
二: 框架的使用
快速上手
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import tornado.ioloop 5 import tornado.web 6 7 8 class MainHandler(tornado.web.RequestHandler): 9 def get(self): 10 self.write("Hello, world") 11 12 application = tornado.web.Application([ 13 (r"/index", MainHandler), 14 ]) 15 16 17 if __name__ == "__main__": 18 application.listen(8888) 19 tornado.ioloop.IOLoop.instance().start()
一:继承requesthandler方法。 创建get方法。
二:配置applicatation 路由映射。
三:执行脚本,监听8888端口。
四: 浏览器访问客户端 http://127.0.0.1:8888/index/
五:服务器接受请求,病交给对应的累处理该请求。
六:类接受请求后,根据请求方式(post,get,delete,put。。。等)不同的调用病执行相应的方法
七:将方法返回的字符串内容返回给浏览器。
获取用户输入的数据
self.get_argument('xxxx')
get: 得到URL输入的参数
post: 得到表单提交等参数。
配置静态文件模板路径
static_path 指明了静态文件所在的路径。
static_path_prefix 表示静态文件的路径前缀。 也可以修改为其他的前缀。例如 /mm/ ,然后再浏览网页的时候会发现静态文件的路径显示为/mm/xxxx
settings = {
'template_path': 'template',
'static_path': 'static',
'static_url_prefix': '/static/',
'ui_methods': mt,
'ui_modules': md,
}
application = tornado.web.Application([
(r"/index", MainHandler),
], **settings) //**settings 指settings字典
三、路由系统
路由系统指的是URL和类的对应关系转换。在其他的很多框架中url对应函数。在tornado中,url对应一个类。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import tornado.ioloop
import tornado.web
class IndexHandler(tornado.web.RequestHandler):
def get(self):
self.write('index')
class HomeHandler(tornado.web.RequestHandler):
def get(self):
self.write('Home')
settings = {
'template_path': 'template',
'static_path': 'static',
'static_url_prefix': '/static/',
}
application = tornado.web.Application([
(r"/index/", IndexHandler),
(r"/home/", HomeHandler),
], **settings)
if __name__ == "__main__":
application.listen(8009)
tornado.ioloop.IOLoop.instance().start()
在tornado中支持二级路由
如果有下列代码,在add_handlers 中添加了一个二级域名,在进行访问的时候,会优先处理StuHandler
application.add_handlers('stu.aa.com', [
(r'/index/',StuHandler),

基于正则的动态路由
1: 使用(\d*)正则表示输入的数据。 浏览器中输入 http://127.0.0.1/124/231。 此时顺序传递参数。
1 application = tornado.web.Application([ 2 (r"/index/(\d*)/(\d*)",home.IndexHandler), 3 ],**settings)
2:也可以通过制定参数名称传递参数
1 application = tornado.web.Application([ 2 (r"/index/(?P<num>\d*)/(?P<nid>\d*)",home.IndexHandler), 3 ],**settings)
传递过来的参数在第一种情况下顺序匹配。 第二种情况下按照名称匹配。
1 class IndexHandler(tornado.web.RequestHandler): 2 def get(self,nid,num): 3 print(nid,num)
四、模板引擎
Tornado中的模板语言和digango类似。 模板引擎讲模板文件载入到内存,然后将数据嵌入其中。 最终获取到一个完成的字符串。在将字符串返回给请求者。
Tornado的模板支持“控制语句”和“表达语句”。控制语句是使用{% 和 %} 包起来。 例如{%if len(items)>2 %} 表达式语句是使用{{ 和 }} 包起来的。例如{{ item[0] }}。
控制语句和对应的python语句的格式基本完全相同。我们支持使用if、for、while、try。这些语句逻辑解释的位置需要使用{% end %} 做标记。 还通过 extends 和block 语句实现了模板继承。 这些在template 模块的代码文档中有详细描述。
在使用模板前需要在setting中设置模板路径: “template_path” : "tpl"
基本使用:
1:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> 5 <title>老男孩</title> 6 <!--<link href='{{static_url("css/common.css")}}' rel="stylesheet" />--> 7 </head> 8 <body> 9 10 <div> 11 <ul> 12 {% for item in list_info %} 13 <li>{{item}}</li> 14 {% end %} 15 </ul> 16 </div> 17 18 <!--<script src='{{static_url("js/jqurey-3.1.0.js")}}'></script>--> 19 20 </body> 21 </html>
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import tornado.ioloop 5 import tornado.web 6 7 8 class MainHandler(tornado.web.RequestHandler): 9 def get(self): 10 print("ok1") 11 self.render("index.html", list_info=[11, 22, 33]) 12 13 settings = { 14 'template_path': 'tpl', 15 'static_path': 'static', 16 'static_url_prefix': '/static/', 17 } 18 application = tornado.web.Application([ 19 (r"/index/", MainHandler), 20 ],**settings) 21 22 if __name__ == "__main__": 23 application.listen(8888) 24 tornado.ioloop.IOLoop.instance().start()
2:其他常用方法
在模板中默认提供了一些函数、字段、类以供模板使用:
escape: tornado.escape.xhtml_escape 的別名
xhtml_escape: tornado.escape.xhtml_escape 的別名
url_escape: tornado.esca
1 {% extends 'layout.html'%} 2 {% block CSS %} 3 <link href="{{static_url("css/index.css")}}" rel="stylesheet" /> 4 {% end %} 5 6 {% block RenderBody %} 7 <h1>Index</h1> 8 9 <ul> 10 {% for item in li %} 11 <li>{{item}}</li> 12 {% end %} 13 </ul> 14 15 {% end %} 16 17 {% block JavaScript %} 18 19 {% end %} 20 21 index.html
pe.url_escape 的別名
json_encode: tornado.escape.json_encode 的別名
squeeze: tornado.escape.squeeze 的別名
linkify: tornado.escape.linkify 的別名
datetime: Python 的 datetime 模组
handler: 当前的 RequestHandler 对象
request: handler.request 的別名
current_user: handler.current_user 的別名
locale: handler.locale 的別名
_: handler.locale.translate 的別名
static_url: for handler.static_url 的別名 缓存静态文件 当文件修改的时候,MD5才发生变化
xsrf_form_html: handler.xsrf_form_html 的別名
3:母版
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> 5 <title>老男孩</title> 6 <link href="{{static_url("css/common.css")}}" rel="stylesheet" /> 7 {% block CSS %}{% end %} 8 </head> 9 <body> 10 11 <div class="pg-header"> 12 13 </div> 14 15 {% block RenderBody %}{% end %} 16 17 <script src="{{static_url("js/jquery-1.8.2.min.js")}}"></script> 18 19 {% block JavaScript %}{% end %} 20 </body> 21 </html> 22 23 layout.html
1 {% extends 'layout.html'%} 2 {% block CSS %} 3 <link href="{{static_url("css/index.css")}}" rel="stylesheet" /> 4 {% end %} 5 6 {% block RenderBody %} 7 <h1>Index</h1> 8 9 <ul> 10 {% for item in li %} 11 <li>{{item}}</li> 12 {% end %} 13 </ul> 14 15 {% end %} 16 17 {% block JavaScript %} 18 19 {% end %} 20 21 index.html
4: 导入
1 <div> 2 <ul> 3 <li>1024</li> 4 <li>42区</li> 5 </ul> 6 </div> 7 8 header.html
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> 5 <title>老男孩</title> 6 <link href="{{static_url("css/common.css")}}" rel="stylesheet" /> 7 </head> 8 <body> 9 10 <div class="pg-header"> 11 {% include 'header.html' %} 12 </div> 13 14 <script src="{{static_url("js/jquery-1.8.2.min.js")}}"></script> 15 16 </body> 17 </html> 18 19 index.html
5: 自定义函数或者自定义类 UImethod 和UImodule
1 def func(self): 2 return 123
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 from tornado.web import UIModule 4 from tornado import escape 5 6 class custom(UIModule): 7 def render(self, *args, **kwargs): 8 return '<h1>ok</h1>'
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 #!/usr/bin/env python 4 # -*- coding:utf-8 -*- 5 6 import tornado.ioloop 7 import tornado.web 8 from tornado.escape import linkify 9 import uimethod as mt 10 import uimodule as me 11 12 class MainHandler(tornado.web.RequestHandler): 13 def get(self): 14 self.render('index.html') 15 16 settings = { 17 'template_path': 'tpl', 18 'static_path': 'static', 19 'static_url_prefix': '/static/', 20 'ui_methods': mt, 21 'ui_modules': me, 22 } 23 24 application = tornado.web.Application([ 25 (r"/index/", MainHandler), 26 ], **settings) 27 28 29 if __name__ == "__main__": 30 application.listen(8009) 31 tornado.ioloop.IOLoop.instance().start()
1 <!DOCTYPE html> 2 <html> 3 <head lang="en"> 4 <meta charset="UTF-8"> 5 <title></title> 6 <link href="{{static_url("commons.css")}}" rel="stylesheet" /> 7 </head> 8 <body> 9 <h1>hello</h1> 10 {% module custom(123) %} 11 {{ func() }} 12 </body>
五、静态文件
对于静态文件,可以配置静态文件的目录和前端使用时的前缀,并且Tornado 支持静态文件的缓存
下面的实例中 设置了 'static_path': 'static', 后需要去/static/common.js 找文件,在设置了
'static_url_prefix': '/static/' 后默认静态文件目录前缀为static,可以直接写作common.js
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import tornado.ioloop 5 import tornado.web 6 7 8 class MainHandler(tornado.web.RequestHandler): 9 def get(self): 10 self.render('home/index.html') 11 12 settings = { 13 'template_path': 'template', 14 'static_path': 'static', 15 'static_url_prefix': '/static/', 16 } 17 18 application = tornado.web.Application([ 19 (r"/index", MainHandler), 20 ], **settings) 21 22 23 if __name__ == "__main__": 24 application.listen(80) 25 tornado.ioloop.IOLoop.instance().start() 26 27 app.py
1 <!DOCTYPE html> 2 <html> 3 <head lang="en"> 4 <meta charset="UTF-8"> 5 <title></title> 6 <link href="{{static_url("commons.css")}}" rel="stylesheet" /> 7 </head> 8 <body> 9 <h1>hello</h1> 10 </body> 11 </html>
使用了静态文件后,静态文件会生成一个MD5值,只有当静态文件发生变化,MD5才会发生变化。这个时候会更新资源。
六、Cookie
1:普通使用
- 1: def set_cookie(self, name, value, domain=None, expires=None, path="/",
- expires_days=None, **kwargs):
- 2: self.set_cookie("auth",'1', expires= time.time()+10) 设置cookie auth 数值为1, 过期时间为10 秒.。
expires_day =7 表示过期为7天
domian 指明是具体哪个域名的cookie
设置后,用户在访问过程中。将携带次cookie
- 3: selft.get_cookie("auth") 得到cookie的值。
- 4: 一般在退出的时候,需要清除cookie
- 5: 在访问的时候,可以携带多个cookie信息。 例如携带用户名称,进行用户区分
- self.set_cookie("username",name)
- self.set_cookie("auth",1)
2: cookie 签名(加密)
Cookie 很容易被恶意的客户端伪造。加入你想在 cookie 中保存当前登陆用户的 id 之类的信息,你需要对 cookie 作签名以防止伪造。Tornado 通过 set_secure_cookie 和 get_secure_cookie 方法直接支持了这种功能。 要使用这些方法,你需要在创建应用时提供一个密钥,名字为 cookie_secret。 你可以把它作为一个关键词参数传入应用的设置中:
class MainHandler(tornado.web.RequestHandler): def get(self): if not self.get_secure_cookie("mycookie"): self.set_secure_cookie("mycookie", "myvalue") self.write("Your cookie was not set yet!") else: self.write("Your cookie was set!") application = tornado.web.Application([ (r"/", MainHandler), ], cookie_secret="61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=")
1 def _create_signature_v1(secret, *parts): 2 hash = hmac.new(utf8(secret), digestmod=hashlib.sha1) 3 for part in parts: 4 hash.update(utf8(part)) 5 return utf8(hash.hexdigest()) 6 7 # 加密 8 def _create_signature_v2(secret, s): 9 hash = hmac.new(utf8(secret), digestmod=hashlib.sha256) 10 hash.update(utf8(s)) 11 return utf8(hash.hexdigest()) 12 13 def create_signed_value(secret, name, value, version=None, clock=None, 14 key_version=None): 15 if version is None: 16 version = DEFAULT_SIGNED_VALUE_VERSION 17 if clock is None: 18 clock = time.time 19 20 timestamp = utf8(str(int(clock()))) 21 value = base64.b64encode(utf8(value)) 22 if version == 1: 23 signature = _create_signature_v1(secret, name, value, timestamp) 24 value = b"|".join([value, timestamp, signature]) 25 return value 26 elif version == 2: 27 # The v2 format consists of a version number and a series of 28 # length-prefixed fields "%d:%s", the last of which is a 29 # signature, all separated by pipes. All numbers are in 30 # decimal format with no leading zeros. The signature is an 31 # HMAC-SHA256 of the whole string up to that point, including 32 # the final pipe. 33 # 34 # The fields are: 35 # - format version (i.e. 2; no length prefix) 36 # - key version (integer, default is 0) 37 # - timestamp (integer seconds since epoch) 38 # - name (not encoded; assumed to be ~alphanumeric) 39 # - value (base64-encoded) 40 # - signature (hex-encoded; no length prefix) 41 def format_field(s): 42 return utf8("%d:" % len(s)) + utf8(s) 43 to_sign = b"|".join([ 44 b"2", 45 format_field(str(key_version or 0)), 46 format_field(timestamp), 47 format_field(name), 48 format_field(value), 49 b'']) 50 51 if isinstance(secret, dict): 52 assert key_version is not None, 'Key version must be set when sign key dict is used' 53 assert version >= 2, 'Version must be at least 2 for key version support' 54 secret = secret[key_version] 55 56 signature = _create_signature_v2(secret, to_sign) 57 return to_sign + signature 58 else: 59 raise ValueError("Unsupported version %d" % version) 60 61 # 解密 62 def _decode_signed_value_v1(secret, name, value, max_age_days, clock): 63 parts = utf8(value).split(b"|") 64 if len(parts) != 3: 65 return None 66 signature = _create_signature_v1(secret, name, parts[0], parts[1]) 67 if not _time_independent_equals(parts[2], signature): 68 gen_log.warning("Invalid cookie signature %r", value) 69 return None 70 timestamp = int(parts[1]) 71 if timestamp < clock() - max_age_days * 86400: 72 gen_log.warning("Expired cookie %r", value) 73 return None 74 if timestamp > clock() + 31 * 86400: 75 # _cookie_signature does not hash a delimiter between the 76 # parts of the cookie, so an attacker could transfer trailing 77 # digits from the payload to the timestamp without altering the 78 # signature. For backwards compatibility, sanity-check timestamp 79 # here instead of modifying _cookie_signature. 80 gen_log.warning("Cookie timestamp in future; possible tampering %r", 81 value) 82 return None 83 if parts[1].startswith(b"0"): 84 gen_log.warning("Tampered cookie %r", value) 85 return None 86 try: 87 return base64.b64decode(parts[0]) 88 except Exception: 89 return None 90 91 92 def _decode_fields_v2(value): 93 def _consume_field(s): 94 length, _, rest = s.partition(b':') 95 n = int(length) 96 field_value = rest[:n] 97 # In python 3, indexing bytes returns small integers; we must 98 # use a slice to get a byte string as in python 2. 99 if rest[n:n + 1] != b'|': 100 raise ValueError("malformed v2 signed value field") 101 rest = rest[n + 1:] 102 return field_value, rest 103 104 rest = value[2:] # remove version number 105 key_version, rest = _consume_field(rest) 106 timestamp, rest = _consume_field(rest) 107 name_field, rest = _consume_field(rest) 108 value_field, passed_sig = _consume_field(rest) 109 return int(key_version), timestamp, name_field, value_field, passed_sig 110 111 112 def _decode_signed_value_v2(secret, name, value, max_age_days, clock): 113 try: 114 key_version, timestamp, name_field, value_field, passed_sig = _decode_fields_v2(value) 115 except ValueError: 116 return None 117 signed_string = value[:-len(passed_sig)] 118 119 if isinstance(secret, dict): 120 try: 121 secret = secret[key_version] 122 except KeyError: 123 return None 124 125 expected_sig = _create_signature_v2(secret, signed_string) 126 if not _time_independent_equals(passed_sig, expected_sig): 127 return None 128 if name_field != utf8(name): 129 return None 130 timestamp = int(timestamp) 131 if timestamp < clock() - max_age_days * 86400: 132 # The signature has expired. 133 return None 134 try: 135 return base64.b64decode(value_field) 136 except Exception: 137 return None 138 139 140 def get_signature_key_version(value): 141 value = utf8(value) 142 version = _get_version(value) 143 if version < 2: 144 return None 145 try: 146 key_version, _, _, _, _ = _decode_fields_v2(value) 147 except ValueError: 148 return None 149 150 return key_version
1 写cookie过程: 2 3 将值进行base64加密 4 对除值以外的内容进行签名,哈希算法(无法逆向解析) 5 拼接 签名 + 加密值 6 读cookie过程: 7 8 读取 签名 + 加密值 9 对签名进行验证 10 base64解密,获取值内容
注:许多API验证机制和安全cookie的实现机制相同。
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import tornado.ioloop 5 import tornado.web 6 7 8 class MainHandler(tornado.web.RequestHandler): 9 10 def get(self): 11 login_user = self.get_secure_cookie("login_user", None) 12 if login_user: 13 self.write(login_user) 14 else: 15 self.redirect('/login') 16 17 18 class LoginHandler(tornado.web.RequestHandler): 19 def get(self): 20 self.current_user() 21 22 self.render('login.html', **{'status': ''}) 23 24 def post(self, *args, **kwargs): 25 26 username = self.get_argument('name') 27 password = self.get_argument('pwd') 28 if username == 'yan' and password == '123': 29 self.set_secure_cookie('login_user', 'yan') 30 self.redirect('/') 31 else: 32 self.render('login.html', **{'status': '用户名或密码错误'}) 33 34 settings = { 35 'template_path': 'template', 36 'static_path': 'static', 37 'static_url_prefix': '/static/', 38 'cookie_secret': 'aiuasdhflashjdfoiuashdfiuh' 39 } 40 41 application = tornado.web.Application([ 42 (r"/index", MainHandler), 43 (r"/login", LoginHandler), 44 ], **settings) 45 46 47 if __name__ == "__main__": 48 application.listen(8888) 49 tornado.ioloop.IOLoop.instance().start() 50 51 基于Cookie实现用户验证-Demo
@tornado.web.authenticated 提供的用来进行验证用户是否登录的装饰器
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import tornado.ioloop 5 import tornado.web 6 7 class BaseHandler(tornado.web.RequestHandler): 8 9 def get_current_user(self): 10 return self.get_secure_cookie("login_user") 11 12 class MainHandler(BaseHandler): 13 14 @tornado.web.authenticated 15 def get(self): 16 login_user = self.current_user 17 self.write(login_user) 18 19 20 21 class LoginHandler(tornado.web.RequestHandler): 22 def get(self): 23 self.current_user() 24 25 self.render('login.html', **{'status': ''}) 26 27 def post(self, *args, **kwargs): 28 29 username = self.get_argument('name') 30 password = self.get_argument('pwd') 31 if username == 'yan' and password == '123': 32 self.set_secure_cookie('login_user', 'yan') 33 self.redirect('/') 34 else: 35 self.render('login.html', **{'status': '用户名或密码错误'}) 36 37 settings = { 38 'template_path': 'template', 39 'static_path': 'static', 40 'static_url_prefix': '/static/', 41 'cookie_secret': 'aiuasdhflashjdfoiuashdfiuh', 42 'login_url': '/login' 43 } 44 45 application = tornado.web.Application([ 46 (r"/index", MainHandler), 47 (r"/login", LoginHandler), 48 ], **settings) 49 50 51 if __name__ == "__main__": 52 application.listen(8888) 53 tornado.ioloop.IOLoop.instance().start()
3:JavaScript操作Cookie
由于Cookie保存在浏览器端,所以在浏览器端也可以使用JavaScript来操作Cookie。
1 /* 2 设置cookie,指定秒数过期 3 */ 4 function setCookie(name,value,expires){ 5 var temp = []; 6 var current_date = new Date(); 7 current_date.setSeconds(current_date.getSeconds() + 5); 8 document.cookie = name + "= "+ value +";expires=" + current_date.toUTCString(); 9 }
对于参数:
domain 指定域名下的cookie
path 域名下指定url中的cookie
secure https使用
注:jQuery中也有指定的插件 jQuery Cookie 专门用于操作cookie
七、CSRF
跨站伪造请求(Cross-site request forgery)
在设置csrf后,在请求的时候,后端自动会给前端发送一个证书。 此证书也会保存到cookie中
{{ xsrf_form_html() }}
在html中,需要携带xsrf_form_html 的信息发送到后台。
1 settings = { 2 "xsrf_cookies": True, 3 } 4 application = tornado.web.Application([ 5 (r"/", MainHandler), 6 (r"/login", LoginHandler), 7 ], **settings)
1 <form action="/new_message" method="post"> 2 {{ xsrf_form_html() }} 3 <input type="text" name="message"/> 4 <input type="submit" value="Post"/> 5 </form>
1 function getCookie(name) { 2 var r = document.cookie.match("\\b" + name + "=([^;]*)\\b"); 3 return r ? r[1] : undefined; 4 } 5 6 jQuery.postJSON = function(url, args, callback) { 7 args._xsrf = getCookie("_xsrf"); 8 $.ajax({url: url, data: $.param(args), dataType: "text", type: "POST", 9 success: function(response) { 10 callback(eval("(" + response + ")")); 11 }}); 12 };
1 2 function SubmitCsrf(){ 3 4 var nid = getCookie("_xsrf"); 5 6 $.post({ 7 url:'/csrf', 8 data:{ 9 "k1":"v1", 10 "_xsrf":nid}, 11 success:function(callback){ 12 console.log(callback); 13 } 14 } 15 )}
八、上传文件操作
self.get_argument 的本质是通过self.request 获得数据。 所以可以通过self.request 得到参数。 可以通过meta['filename'] 和 meta['body'] 得到我们想要的内容
1: Form表单上传 表单需要填写enctype="multipart/form-data"
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> 5 <title>上传文件</title> 6 </head> 7 <body> 8 <form id="my_form" name="form" action="/index" method="POST" enctype="multipart/form-data" > 9 <input name="fff" id="my_file" type="file" /> 10 <input type="submit" value="提交" /> 11 </form> 12 </body> 13 </html>
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import tornado.ioloop 5 import tornado.web 6 7 8 class MainHandler(tornado.web.RequestHandler): 9 def get(self): 10 11 self.render('index.html') 12 13 def post(self, *args, **kwargs): 14 file_metas = self.request.files["fff"] 15 # print(file_metas) 16 for meta in file_metas: 17 file_name = meta['filename'] 18 with open(file_name,'wb') as up: 19 up.write(meta['body']) 20 21 settings = { 22 'template_path': 'template', 23 } 24 25 application = tornado.web.Application([ 26 (r"/index", MainHandler), 27 ], **settings) 28 29 30 if __name__ == "__main__": 31 application.listen(8000) 32 tornado.ioloop.IOLoop.instance().start()
2:AJAX上传
Ajax 上传的本质是建立FormData()对象,然后再FormData()中append 数据。然后讲FormData() 提交给后台。
1 <!DOCTYPE html> 2 <html> 3 <head lang="en"> 4 <meta charset="UTF-8"> 5 <title></title> 6 </head> 7 <body> 8 <input type="file" id="img" /> 9 <input type="button" onclick="UploadFile();" /> 10 <script> 11 function UploadFile(){ 12 var fileObj = document.getElementById("img").files[0]; 13 14 var form = new FormData(); 15 form.append("k1", "v1"); 16 form.append("fff", fileObj); 17 18 var xhr = new XMLHttpRequest(); 19 xhr.open("post", '/index', true); 20 xhr.send(form); 21 } 22 </script> 23 </body> 24 </html>
1 <!DOCTYPE html> 2 <html> 3 <head lang="en"> 4 <meta charset="UTF-8"> 5 <title></title> 6 </head> 7 <body> 8 <input type="file" id="img" /> 9 <input type="button" onclick="UploadFile();" /> 10 <script> 11 function UploadFile(){ 12 var fileObj = $("#img")[0].files[0]; 13 var form = new FormData(); 14 form.append("k1", "v1"); 15 form.append("fff", fileObj); 16 17 $.ajax({ 18 type:'POST', 19 url: '/index', 20 data: form, 21 processData: false, // tell jQuery not to process the data 22 contentType: false, // tell jQuery not to set contentType 23 success: function(arg){ 24 console.log(arg); 25 } 26 }) 27 } 28 </script> 29 </body> 30 </html>
1 <!DOCTYPE html> 2 <html> 3 <head lang="en"> 4 <meta charset="UTF-8"> 5 <title></title> 6 </head> 7 <body> 8 <form id="my_form" name="form" action="/index" method="POST" enctype="multipart/form-data" > 9 <div id="main"> 10 <input name="fff" id="my_file" type="file" /> 11 <input type="button" name="action" value="Upload" onclick="redirect()"/> 12 <iframe id='my_iframe' name='my_iframe' src="" class="hide"></iframe> 13 </div> 14 </form> 15 16 <script> 17 function redirect(){ 18 document.getElementById('my_iframe').onload = Testt; 19 document.getElementById('my_form').target = 'my_iframe'; 20 document.getElementById('my_form').submit(); 21 22 } 23 24 function Testt(ths){ 25 var t = $("#my_iframe").contents().find("body").text(); 26 console.log(t); 27 } 28 </script> 29 </body> 30 </html>
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import tornado.ioloop 5 import tornado.web 6 7 8 class MainHandler(tornado.web.RequestHandler): 9 def get(self): 10 11 self.render('index.html') 12 13 def post(self, *args, **kwargs): 14 file_metas = self.request.files["fff"] 15 # print(file_metas) 16 for meta in file_metas: 17 file_name = meta['filename'] 18 with open(file_name,'wb') as up: 19 up.write(meta['body']) 20 21 settings = { 22 'template_path': 'template', 23 } 24 25 application = tornado.web.Application([ 26 (r"/index", MainHandler), 27 ], **settings) 28 29 30 if __name__ == "__main__": 31 application.listen(8000) 32 tornado.ioloop.IOLoop.instance().start()
1 <script type="text/javascript"> 2 3 $(document).ready(function () { 4 5 $("#formsubmit").click(function () { 6 7 var iframe = $('<iframe name="postiframe" id="postiframe" style="display: none"></iframe>'); 8 9 $("body").append(iframe); 10 11 var form = $('#theuploadform'); 12 form.attr("action", "/upload.aspx"); 13 form.attr("method", "post"); 14 15 form.attr("encoding", "multipart/form-data"); 16 form.attr("enctype", "multipart/form-data"); 17 18 form.attr("target", "postiframe"); 19 form.attr("file", $('#userfile').val()); 20 form.submit(); 21 22 $("#postiframe").load(function () { 23 iframeContents = this.contentWindow.document.body.innerHTML; 24 $("#textarea").html(iframeContents); 25 }); 26 27 return false; 28 29 }); 30 31 }); 32 33 </script> 34 35 36 <form id="theuploadform"> 37 <input id="userfile" name="userfile" size="50" type="file" /> 38 <input id="formsubmit" type="submit" value="Send File" /> 39 </form> 40 41 <div id="textarea"> 42 </div>
九、验证码
验证码原理在于后台自动创建一张带有随机内容的图片,然后将内容通过img标签输出到页面。
安装图像处理模块:
pip3 install pillow
十、自定义Session
Session是依赖于Cookie实现的
Session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。客户端浏览器再次访问时携带Cookie,然后只需要从该Session中查找该客户的状态就可以了。
1:面向对象的方法
面向对象中通过索引的方式访问对象,需要内部实现 __getitem__ 、__delitem__、__setitem__方法
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 class Foo(object): 5 6 def __getitem__(self, key): 7 print '__getitem__',key 8 9 def __setitem__(self, key, value): 10 print '__setitem__',key,value 11 12 def __delitem__(self, key): 13 print '__delitem__',key 14 15 16 17 obj = Foo() 18 result = obj['k1'] 19 #obj['k2'] = '123' 20 #del obj['k1']
2:Tornado扩展
Tornado框架中,默认执行Handler的get/post等方法之前默认会执行 initialize方法,所以可以通过自定义的方式使得所有请求在处理前执行操作。
1 class BaseHandler(tornado.web.RequestHandler): 2 3 def initialize(self): 4 self.xxoo = "yan" 5 6 7 class MainHandler(BaseHandler): 8 9 def get(self): 10 print(self.xxoo) 11 self.write('index') 12 13 class IndexHandler(BaseHandler): 14 15 def get(self): 16 print(self.xxoo) 17 self.write('index')
3: session
session其实就是定义在服务器端用于保存用户会话的容器,其必须依赖cookie才能实现。
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import tornado.ioloop 5 import tornado.web 6 from hashlib import sha1 7 import os, time 8 9 session_container = {} 10 11 create_session_id = lambda: sha1('%s%s' % (os.urandom(16), time.time())).hexdigest() 12 13 14 class Session(object): 15 16 session_id = "__sessionId__" 17 18 def __init__(self, request): 19 session_value = request.get_cookie(Session.session_id) 20 if not session_value: 21 self._id = create_session_id() 22 else: 23 self._id = session_value 24 request.set_cookie(Session.session_id, self._id) 25 26 def __getitem__(self, key): 27 return session_container[self._id][key] 28 29 def __setitem__(self, key, value): 30 if session_container.has_key(self._id): 31 session_container[self._id][key] = value 32 else: 33 session_container[self._id] = {key: value} 34 35 def __delitem__(self, key): 36 del session_container[self._id][key] 37 38 39 class BaseHandler(tornado.web.RequestHandler): 40 41 def initialize(self): 42 # my_session['k1']访问 __getitem__ 方法 43 self.my_session = Session(self) 44 45 46 class MainHandler(BaseHandler): 47 48 def get(self): 49 print self.my_session['c_user'] 50 print self.my_session['c_card'] 51 self.write('index') 52 53 class LoginHandler(BaseHandler): 54 55 def get(self): 56 self.render('login.html', **{'status': ''}) 57 58 def post(self, *args, **kwargs): 59 60 username = self.get_argument('name') 61 password = self.get_argument('pwd') 62 if username == 'wupeiqi' and password == '123': 63 64 self.my_session['c_user'] = 'wupeiqi' 65 self.my_session['c_card'] = '12312312309823012' 66 67 self.redirect('/index') 68 else: 69 self.render('login.html', **{'status': '用户名或密码错误'}) 70 71 settings = { 72 'template_path': 'template', 73 'static_path': 'static', 74 'static_url_prefix': '/static/', 75 'cookie_secret': 'aiuasdhflashjdfoiuashdfiuh', 76 'login_url': '/login' 77 } 78 79 application = tornado.web.Application([ 80 (r"/index", MainHandler), 81 (r"/login", LoginHandler), 82 ], **settings) 83 84 85 if __name__ == "__main__": 86 application.listen(8888) 87 tornado.ioloop.IOLoop.instance().start()
练习:
1 #!/usr/bin/evn python 2 #-*- coding:utf-8 -*- 3 import tornado.ioloop 4 import tornado.web 5 6 7 container = {} 8 class IndexHandler(tornado.web.RequestHandler): 9 def get(self): 10 if self.get_argument("u",None) in ["yan","yy"]: 11 import hashlib 12 import time 13 obj = hashlib.md5() 14 obj.update(bytes(str(time.time()),encoding="utf-8")) 15 random_str = obj.hexdigest() 16 container[random_str] = {} 17 container[random_str]["k1"] = 123 18 container[random_str]["k2"] = self.get_argument("u",None) + "parent" 19 container[random_str]["is_login"] = True 20 self.set_cookie("aaaaa",random_str) 21 22 else: 23 self.write("请登录") 24 25 26 27 28 class ManageHandler(tornado.web.RequestHandler): 29 def get(self): 30 random_str = self.get_cookie("aaaaa") 31 32 current_user_info = container.get(random_str,"") 33 if not current_user_info: 34 self.redirect("/index/") 35 36 else: 37 if current_user_info.get("is_login",None): 38 temp = "%s -%s"%(current_user_info.get("k1",""),current_user_info.get("k2","")) 39 self.write(temp) 40 41 else: 42 self.redirect("/index/") 43 44 45 46 47 48 49 settings = { 50 'template_path': 'view', 51 'static_path': 'statics', 52 'static_url_prefix': '/static/', 53 } 54 application = tornado.web.Application([ 55 (r"/index/", IndexHandler), 56 (r"/manage/", ManageHandler) 57 ],**settings) 58 59 60 61 62 if __name__ == "__main__": 63 application.listen(8880) 64 tornado.ioloop.IOLoop.instance().start()
1 #!/usr/bin/evn python 2 #-*- coding:utf-8 -*- 3 import tornado.ioloop 4 import tornado.web 5 6 7 container = {} 8 9 10 class Session: 11 def __init__(self, handler): 12 self.handler = handler 13 self.random_str = None 14 15 16 def __generate_randomstr(self): 17 import hashlib 18 import time 19 obj = hashlib.md5() 20 obj.update(bytes(str(time.time()), encoding="utf-8")) 21 random_str = obj.hexdigest() 22 return random_str 23 24 def set_value(self,key,value): 25 #在container中设置随机字符串 26 #定义专属自己的数据 27 #在客户端写入随机字符串 28 if not self.random_str: 29 random_str = self.handler.get_cookie("__aaa") 30 if not random_str: 31 random_str = self.__generate_randomstr() 32 container[random_str] = {} 33 else: 34 #客户端有随机字符串 35 if random_str in container.keys(): 36 pass 37 else: 38 random_str = self.__generate_randomstr() 39 container[random_str] = {} 40 self.random_str = random_str 41 container[self.random_str][key] = value 42 43 self.handler.set_cookie("__aaa", self.random_str) 44 45 46 47 def get_value(self,key): 48 #获取客户端的随机字符串 49 #从container中得到专属信息。得到key的值 50 random_str = self.handler.get_cookie("__aaa") 51 if not random_str: 52 return None 53 54 user_info_dict = container.get(random_str,None) 55 56 if not user_info_dict: 57 return None 58 #客户端有该随机字符串 59 60 value = user_info_dict.get(key,None) 61 return value 62 63 64 class IndexHandler(tornado.web.RequestHandler): 65 def get(self): 66 if self.get_argument("u", None) in ["yan", "yy"]: 67 s = Session(self) 68 s.set_value("is_login",True) 69 s.set_value("name", self.get_argument("u")) 70 else: 71 self.write("请登录") 72 73 74 class ManageHandler(tornado.web.RequestHandler): 75 def get(self): 76 s = Session(self) 77 value = s.get_value("is_login") 78 if value: 79 self.write(s.get_value("name")) 80 else: 81 self.write("失败") 82 83 84 85 86 87 88 settings = { 89 'template_path': 'view', 90 'static_path': 'statics', 91 'static_url_prefix': '/static/', 92 } 93 application = tornado.web.Application([ 94 (r"/index/", IndexHandler), 95 (r"/manage/", ManageHandler) 96 ],**settings) 97 98 99 100 101 if __name__ == "__main__": 102 application.listen(8880) 103 tornado.ioloop.IOLoop.instance().start()
1 #!/usr/bin/evn python 2 #-*- coding:utf-8 -*- 3 import tornado.ioloop 4 import tornado.web 5 6 7 container = {} 8 9 10 class Session: 11 def __init__(self, handler): 12 self.handler = handler 13 self.random_str = None 14 15 16 def __generate_randomstr(self): 17 import hashlib 18 import time 19 obj = hashlib.md5() 20 obj.update(bytes(str(time.time()), encoding="utf-8")) 21 random_str = obj.hexdigest() 22 return random_str 23 24 def set_value(self,key,value): 25 #在container中设置随机字符串 26 #定义专属自己的数据 27 #在客户端写入随机字符串 28 if not self.random_str: 29 random_str = self.handler.get_cookie("__aaa") 30 if not random_str: 31 random_str = self.__generate_randomstr() 32 container[random_str] = {} 33 else: 34 #客户端有随机字符串 35 if random_str in container.keys(): 36 pass 37 else: 38 random_str = self.__generate_randomstr() 39 container[random_str] = {} 40 self.random_str = random_str 41 container[self.random_str][key] = value 42 43 self.handler.set_cookie("__aaa", self.random_str) 44 45 46 47 def get_value(self,key): 48 #获取客户端的随机字符串 49 #从container中得到专属信息。得到key的值 50 random_str = self.handler.get_cookie("__aaa") 51 if not random_str: 52 return None 53 54 user_info_dict = container.get(random_str,None) 55 56 if not user_info_dict: 57 return None 58 #客户端有该随机字符串 59 60 value = user_info_dict.get(key,None) 61 return value 62 63 64 65 66 class BaseHandler(tornado.web.RequestHandler): 67 def initialize(self): 68 self.session = Session(self) 69 70 71 class IndexHandler(BaseHandler): 72 def get(self): 73 if self.get_argument("u", None) in ["yan", "yy"]: 74 self.session.set_value("is_login",True) 75 self.session.set_value("name", self.get_argument("u")) 76 else: 77 self.write("请登录") 78 79 80 class ManageHandler(BaseHandler): 81 def get(self): 82 value = self.session.get_value("is_login") 83 if value: 84 self.write(self.session.get_value("name")) 85 else: 86 self.write("失败") 87 88 89 90 91 92 93 settings = { 94 'template_path': 'view', 95 'static_path': 'statics', 96 'static_url_prefix': '/static/', 97 } 98 application = tornado.web.Application([ 99 (r"/index/", IndexHandler), 100 (r"/manage/", ManageHandler) 101 ],**settings) 102 103 104 105 106 if __name__ == "__main__": 107 application.listen(8880) 108 tornado.ioloop.IOLoop.instance().start()
1 #!/usr/bin/evn python 2 #-*- coding:utf-8 -*- 3 import tornado.ioloop 4 import tornado.web 5 6 7 container = {} 8 9 10 class Session: 11 def __init__(self, handler): 12 self.handler = handler 13 self.random_str = None 14 15 16 def __generate_randomstr(self): 17 import hashlib 18 import time 19 obj = hashlib.md5() 20 obj.update(bytes(str(time.time()), encoding="utf-8")) 21 random_str = obj.hexdigest() 22 return random_str 23 24 #def set_value(self,key,value): 25 def __setitem__(self, key, value): 26 #在container中设置随机字符串 27 #定义专属自己的数据 28 #在客户端写入随机字符串 29 if not self.random_str: 30 random_str = self.handler.get_cookie("__aaa") 31 if not random_str: 32 random_str = self.__generate_randomstr() 33 container[random_str] = {} 34 else: 35 #客户端有随机字符串 36 if random_str in container.keys(): 37 pass 38 else: 39 random_str = self.__generate_randomstr() 40 container[random_str] = {} 41 self.random_str = random_str 42 container[self.random_str][key] = value 43 44 self.handler.set_cookie("__aaa", self.random_str) 45 46 47 48 #def get_value(self,key): 49 def __getitem__(self, key): 50 #获取客户端的随机字符串 51 #从container中得到专属信息。得到key的值 52 random_str = self.handler.get_cookie("__aaa") 53 if not random_str: 54 return None 55 56 user_info_dict = container.get(random_str,None) 57 58 if not user_info_dict: 59 return None 60 #客户端有该随机字符串 61 62 value = user_info_dict.get(key,None) 63 return value 64 65 66 67 68 69 70 71 72 class BaseHandler(tornado.web.RequestHandler): 73 def initialize(self): 74 self.session = Session(self) 75 76 77 class IndexHandler(BaseHandler): 78 def get(self): 79 if self.get_argument("u", None) in ["yan", "yy"]: 80 self.session["is_login"]=True 81 self.session["name"] = self.get_argument("u") 82 else: 83 self.write("请登录") 84 85 86 class ManageHandler(BaseHandler): 87 def get(self): 88 value = self.session["is_login"] 89 if value: 90 self.write(self.session["name"]) 91 else: 92 self.write("失败") 93 94 95 96 97 98 99 settings = { 100 'template_path': 'view', 101 'static_path': 'statics', 102 'static_url_prefix': '/static/', 103 } 104 application = tornado.web.Application([ 105 (r"/index/", IndexHandler), 106 (r"/manage/", ManageHandler) 107 ],**settings) 108 109 110 111 112 if __name__ == "__main__": 113 application.listen(8880) 114 tornado.ioloop.IOLoop.instance().start()
4:扩展分布式Session
1 #!/usr/bin/env python 2 #coding:utf-8 3 4 import sys 5 import math 6 from bisect import bisect 7 8 9 if sys.version_info >= (2, 5): 10 import hashlib 11 md5_constructor = hashlib.md5 12 else: 13 import md5 14 md5_constructor = md5.new 15 16 17 class HashRing(object): 18 """一致性哈希""" 19 20 def __init__(self,nodes): 21 '''初始化 22 nodes : 初始化的节点,其中包含节点已经节点对应的权重 23 默认每一个节点有32个虚拟节点 24 对于权重,通过多创建虚拟节点来实现 25 如:nodes = [ 26 {'host':'127.0.0.1:8000','weight':1}, 27 {'host':'127.0.0.1:8001','weight':2}, 28 {'host':'127.0.0.1:8002','weight':1}, 29 ] 30 ''' 31 32 self.ring = dict() 33 self._sorted_keys = [] 34 35 self.total_weight = 0 36 37 self.__generate_circle(nodes) 38 39 40 41 def __generate_circle(self,nodes): 42 for node_info in nodes: 43 self.total_weight += node_info.get('weight',1) 44 45 for node_info in nodes: 46 weight = node_info.get('weight',1) 47 node = node_info.get('host',None) 48 49 virtual_node_count = math.floor((32*len(nodes)*weight) / self.total_weight) 50 for i in xrange(0,int(virtual_node_count)): 51 key = self.gen_key_thirty_two( '%s-%s' % (node, i) ) 52 if self._sorted_keys.__contains__(key): 53 raise Exception('该节点已经存在.') 54 self.ring[key] = node 55 self._sorted_keys.append(key) 56 57 def add_node(self,node): 58 ''' 新建节点 59 node : 要添加的节点,格式为:{'host':'127.0.0.1:8002','weight':1},其中第一个元素表示节点,第二个元素表示该节点的权重。 60 ''' 61 node = node.get('host',None) 62 if not node: 63 raise Exception('节点的地址不能为空.') 64 65 weight = node.get('weight',1) 66 67 self.total_weight += weight 68 nodes_count = len(self._sorted_keys) + 1 69 70 virtual_node_count = math.floor((32 * nodes_count * weight) / self.total_weight) 71 for i in xrange(0,int(virtual_node_count)): 72 key = self.gen_key_thirty_two( '%s-%s' % (node, i) ) 73 if self._sorted_keys.__contains__(key): 74 raise Exception('该节点已经存在.') 75 self.ring[key] = node 76 self._sorted_keys.append(key) 77 78 def remove_node(self,node): 79 ''' 移除节点 80 node : 要移除的节点 '127.0.0.1:8000' 81 ''' 82 for key,value in self.ring.items(): 83 if value == node: 84 del self.ring[key] 85 self._sorted_keys.remove(key) 86 87 def get_node(self,string_key): 88 '''获取 string_key 所在的节点''' 89 pos = self.get_node_pos(string_key) 90 if pos is None: 91 return None 92 return self.ring[ self._sorted_keys[pos]].split(':') 93 94 def get_node_pos(self,string_key): 95 '''获取 string_key 所在的节点的索引''' 96 if not self.ring: 97 return None 98 99 key = self.gen_key_thirty_two(string_key) 100 nodes = self._sorted_keys 101 pos = bisect(nodes, key) 102 return pos 103 104 def gen_key_thirty_two(self, key): 105 106 m = md5_constructor() 107 m.update(key) 108 return long(m.hexdigest(), 16) 109 110 def gen_key_sixteen(self,key): 111 112 b_key = self.__hash_digest(key) 113 return self.__hash_val(b_key, lambda x: x) 114 115 def __hash_val(self, b_key, entry_fn): 116 return (( b_key[entry_fn(3)] << 24)|(b_key[entry_fn(2)] << 16)|(b_key[entry_fn(1)] << 8)| b_key[entry_fn(0)] ) 117 118 def __hash_digest(self, key): 119 m = md5_constructor() 120 m.update(key) 121 return map(ord, m.digest()) 122 123 124 """ 125 nodes = [ 126 {'host':'127.0.0.1:8000','weight':1}, 127 {'host':'127.0.0.1:8001','weight':2}, 128 {'host':'127.0.0.1:8002','weight':1}, 129 ] 130 131 ring = HashRing(nodes) 132 result = ring.get_node('98708798709870987098709879087') 133 print result 134 135 """
1 from hashlib import sha1 2 import os, time 3 4 5 create_session_id = lambda: sha1('%s%s' % (os.urandom(16), time.time())).hexdigest() 6 7 8 class Session(object): 9 10 session_id = "__sessionId__" 11 12 def __init__(self, request): 13 session_value = request.get_cookie(Session.session_id) 14 if not session_value: 15 self._id = create_session_id() 16 else: 17 self._id = session_value 18 request.set_cookie(Session.session_id, self._id) 19 20 def __getitem__(self, key): 21 # 根据 self._id ,在一致性哈西中找到其对应的服务器IP 22 # 找到相对应的redis服务器,如: r = redis.StrictRedis(host='localhost', port=6379, db=0) 23 # 使用python redis api 链接 24 # 获取数据,即: 25 # return self._redis.hget(self._id, name) 26 27 def __setitem__(self, key, value): 28 # 根据 self._id ,在一致性哈西中找到其对应的服务器IP 29 # 使用python redis api 链接 30 # 设置session 31 # self._redis.hset(self._id, name, value) 32 33 34 def __delitem__(self, key): 35 # 根据 self._id 找到相对应的redis服务器 36 # 使用python redis api 链接 37 # 删除,即: 38 return self._redis.hdel(self._id, name)
十一、自定义Form表单验证
1 <!DOCTYPE html> 2 <html> 3 <head lang="en"> 4 <meta charset="UTF-8"> 5 <title></title> 6 <link href="{{static_url("commons.css")}}" rel="stylesheet" /> 7 </head> 8 <body> 9 <h1>hello</h1> 10 <form action="/index" method="post"> 11 12 <p>hostname: <input type="text" name="host" /> </p> 13 <p>ip: <input type="text" name="ip" /> </p> 14 <p>port: <input type="text" name="port" /> </p> 15 <p>phone: <input type="text" name="phone" /> </p> 16 <input type="submit" /> 17 </form> 18 </body> 19 </html>
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import tornado.ioloop 5 import tornado.web 6 from hashlib import sha1 7 import os, time 8 import re 9 10 11 class MainForm(object): 12 def __init__(self): 13 self.host = "(.*)" 14 self.ip = "^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$" 15 self.port = '(\d+)' 16 self.phone = '^1[3|4|5|8][0-9]\d{8}$' 17 18 def check_valid(self, request): 19 form_dict = self.__dict__ 20 for key, regular in form_dict.items(): 21 post_value = request.get_argument(key) 22 # 让提交的数据 和 定义的正则表达式进行匹配 23 ret = re.match(regular, post_value) 24 print key,ret,post_value 25 26 27 class MainHandler(tornado.web.RequestHandler): 28 def get(self): 29 self.render('index.html') 30 def post(self, *args, **kwargs): 31 obj = MainForm() 32 result = obj.check_valid(self) 33 self.write('ok') 34 35 36 37 settings = { 38 'template_path': 'template', 39 'static_path': 'static', 40 'static_url_prefix': '/static/', 41 'cookie_secret': 'aiuasdhflashjdfoiuashdfiuh', 42 'login_url': '/login' 43 } 44 45 application = tornado.web.Application([ 46 (r"/index", MainHandler), 47 ], **settings) 48 49 50 if __name__ == "__main__": 51 application.listen(8888) 52 tornado.ioloop.IOLoop.instance().start()
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import tornado.ioloop 5 import tornado.web 6 import re 7 8 9 class Field(object): 10 11 def __init__(self, error_msg_dict, required): 12 self.id_valid = False 13 self.value = None 14 self.error = None 15 self.name = None 16 self.error_msg = error_msg_dict 17 self.required = required 18 19 def match(self, name, value): 20 self.name = name 21 22 if not self.required: 23 self.id_valid = True 24 self.value = value 25 else: 26 if not value: 27 if self.error_msg.get('required', None): 28 self.error = self.error_msg['required'] 29 else: 30 self.error = "%s is required" % name 31 else: 32 ret = re.match(self.REGULAR, value) 33 if ret: 34 self.id_valid = True 35 self.value = ret.group() 36 else: 37 if self.error_msg.get('valid', None): 38 self.error = self.error_msg['valid'] 39 else: 40 self.error = "%s is invalid" % name 41 42 43 class IPField(Field): 44 REGULAR = "^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$" 45 46 def __init__(self, error_msg_dict=None, required=True): 47 48 error_msg = {} # {'required': 'IP不能为空', 'valid': 'IP格式错误'} 49 if error_msg_dict: 50 error_msg.update(error_msg_dict) 51 52 super(IPField, self).__init__(error_msg_dict=error_msg, required=required) 53 54 55 class IntegerField(Field): 56 REGULAR = "^\d+$" 57 58 def __init__(self, error_msg_dict=None, required=True): 59 error_msg = {'required': '数字不能为空', 'valid': '数字格式错误'} 60 if error_msg_dict: 61 error_msg.update(error_msg_dict) 62 63 super(IntegerField, self).__init__(error_msg_dict=error_msg, required=required) 64 65 66 class CheckBoxField(Field): 67 68 def __init__(self, error_msg_dict=None, required=True): 69 error_msg = {} # {'required': 'IP不能为空', 'valid': 'IP格式错误'} 70 if error_msg_dict: 71 error_msg.update(error_msg_dict) 72 73 super(CheckBoxField, self).__init__(error_msg_dict=error_msg, required=required) 74 75 def match(self, name, value): 76 self.name = name 77 78 if not self.required: 79 self.id_valid = True 80 self.value = value 81 else: 82 if not value: 83 if self.error_msg.get('required', None): 84 self.error = self.error_msg['required'] 85 else: 86 self.error = "%s is required" % name 87 else: 88 if isinstance(name, list): 89 self.id_valid = True 90 self.value = value 91 else: 92 if self.error_msg.get('valid', None): 93 self.error = self.error_msg['valid'] 94 else: 95 self.error = "%s is invalid" % name 96 97 98 class FileField(Field): 99 REGULAR = "^(\w+\.pdf)|(\w+\.mp3)|(\w+\.py)$" 100 101 def __init__(self, error_msg_dict=None, required=True): 102 error_msg = {} # {'required': '数字不能为空', 'valid': '数字格式错误'} 103 if error_msg_dict: 104 error_msg.update(error_msg_dict) 105 106 super(FileField, self).__init__(error_msg_dict=error_msg, required=required) 107 108 def match(self, name, value): 109 self.name = name 110 self.value = [] 111 if not self.required: 112 self.id_valid = True 113 self.value = value 114 else: 115 if not value: 116 if self.error_msg.get('required', None): 117 self.error = self.error_msg['required'] 118 else: 119 self.error = "%s is required" % name 120 else: 121 m = re.compile(self.REGULAR) 122 if isinstance(value, list): 123 for file_name in value: 124 r = m.match(file_name) 125 if r: 126 self.value.append(r.group()) 127 self.id_valid = True 128 else: 129 self.id_valid = False 130 if self.error_msg.get('valid', None): 131 self.error = self.error_msg['valid'] 132 else: 133 self.error = "%s is invalid" % name 134 break 135 else: 136 if self.error_msg.get('valid', None): 137 self.error = self.error_msg['valid'] 138 else: 139 self.error = "%s is invalid" % name 140 141 def save(self, request, upload_path=""): 142 143 file_metas = request.files[self.name] 144 for meta in file_metas: 145 file_name = meta['filename'] 146 with open(file_name,'wb') as up: 147 up.write(meta['body']) 148 149 150 class Form(object): 151 152 def __init__(self): 153 self.value_dict = {} 154 self.error_dict = {} 155 self.valid_status = True 156 157 def validate(self, request, depth=10, pre_key=""): 158 159 self.initialize() 160 self.__valid(self, request, depth, pre_key) 161 162 def initialize(self): 163 pass 164 165 def __valid(self, form_obj, request, depth, pre_key): 166 """ 167 验证用户表单请求的数据 168 :param form_obj: Form对象(Form派生类的对象) 169 :param request: Http请求上下文(用于从请求中获取用户提交的值) 170 :param depth: 对Form内容的深度的支持 171 :param pre_key: Html中name属性值的前缀(多层Form时,内部递归时设置,无需理会) 172 :return: 是否验证通过,True:验证成功;False:验证失败 173 """ 174 175 depth -= 1 176 if depth < 0: 177 return None 178 form_field_dict = form_obj.__dict__ 179 for key, field_obj in form_field_dict.items(): 180 print key,field_obj 181 if isinstance(field_obj, Form) or isinstance(field_obj, Field): 182 if isinstance(field_obj, Form): 183 # 获取以key开头的所有的值,以参数的形式传至 184 self.__valid(field_obj, request, depth, key) 185 continue 186 if pre_key: 187 key = "%s.%s" % (pre_key, key) 188 189 if isinstance(field_obj, CheckBoxField): 190 post_value = request.get_arguments(key, None) 191 elif isinstance(field_obj, FileField): 192 post_value = [] 193 file_list = request.request.files.get(key, None) 194 for file_item in file_list: 195 post_value.append(file_item['filename']) 196 else: 197 post_value = request.get_argument(key, None) 198 199 print post_value 200 # 让提交的数据 和 定义的正则表达式进行匹配 201 field_obj.match(key, post_value) 202 if field_obj.id_valid: 203 self.value_dict[key] = field_obj.value 204 else: 205 self.error_dict[key] = field_obj.error 206 self.valid_status = False 207 208 209 class ListForm(object): 210 def __init__(self, form_type): 211 self.form_type = form_type 212 self.valid_status = True 213 self.value_dict = {} 214 self.error_dict = {} 215 216 def validate(self, request): 217 name_list = request.request.arguments.keys() + request.request.files.keys() 218 index = 0 219 flag = False 220 while True: 221 pre_key = "[%d]" % index 222 for name in name_list: 223 if name.startswith(pre_key): 224 flag = True 225 break 226 if flag: 227 form_obj = self.form_type() 228 form_obj.validate(request, depth=10, pre_key="[%d]" % index) 229 if form_obj.valid_status: 230 self.value_dict[index] = form_obj.value_dict 231 else: 232 self.error_dict[index] = form_obj.error_dict 233 self.valid_status = False 234 else: 235 break 236 237 index += 1 238 flag = False 239 240 241 class MainForm(Form): 242 243 def __init__(self): 244 # self.ip = IPField(required=True) 245 # self.port = IntegerField(required=True) 246 # self.new_ip = IPField(required=True) 247 # self.second = SecondForm() 248 self.fff = FileField(required=True) 249 super(MainForm, self).__init__() 250 251 # 252 # class SecondForm(Form): 253 # 254 # def __init__(self): 255 # self.ip = IPField(required=True) 256 # self.new_ip = IPField(required=True) 257 # 258 # super(SecondForm, self).__init__() 259 260 261 class MainHandler(tornado.web.RequestHandler): 262 def get(self): 263 self.render('index.html') 264 def post(self, *args, **kwargs): 265 # for i in dir(self.request): 266 # print i 267 # print self.request.arguments 268 # print self.request.files 269 # print self.request.query 270 # name_list = self.request.arguments.keys() + self.request.files.keys() 271 # print name_list 272 273 # list_form = ListForm(MainForm) 274 # list_form.validate(self) 275 # 276 # print list_form.valid_status 277 # print list_form.value_dict 278 # print list_form.error_dict 279 280 # obj = MainForm() 281 # obj.validate(self) 282 # 283 # print "验证结果:", obj.valid_status 284 # print "符合验证结果:", obj.value_dict 285 # print "错误信息:" 286 # for key, item in obj.error_dict.items(): 287 # print key,item 288 # print self.get_arguments('favor'),type(self.get_arguments('favor')) 289 # print self.get_argument('favor'),type(self.get_argument('favor')) 290 # print type(self.get_argument('fff')),self.get_argument('fff') 291 # print self.request.files 292 # obj = MainForm() 293 # obj.validate(self) 294 # print obj.valid_status 295 # print obj.value_dict 296 # print obj.error_dict 297 # print self.request,type(self.request) 298 # obj.fff.save(self.request) 299 # from tornado.httputil import HTTPServerRequest 300 # name_list = self.request.arguments.keys() + self.request.files.keys() 301 # print name_list 302 # print self.request.files,type(self.request.files) 303 # print len(self.request.files.get('fff')) 304 305 # obj = MainForm() 306 # obj.validate(self) 307 # print obj.valid_status 308 # print obj.value_dict 309 # print obj.error_dict 310 # obj.fff.save(self.request) 311 self.write('ok') 312 313 314 315 settings = { 316 'template_path': 'template', 317 'static_path': 'static', 318 'static_url_prefix': '/static/', 319 'cookie_secret': 'aiuasdhflashjdfoiuashdfiuh', 320 'login_url': '/login' 321 } 322 323 application = tornado.web.Application([ 324 (r"/index", MainHandler), 325 ], **settings) 326 327 328 if __name__ == "__main__": 329 application.listen(8888) 330 tornado.ioloop.IOLoop.instance().start()
练习:
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import tornado.ioloop 5 import tornado.web 6 from hashlib import sha1 7 import os, time 8 import re 9 10 11 12 class IndexHandler(tornado.web.RequestHandler): 13 def get(self): 14 self.render("index.html") 15 16 def post(self): 17 obj = IndexForm() 18 is_valid,value_dict = obj.check_valid(self) 19 print(is_valid) 20 21 #如果全部验证成功,将用胡俗人的数据全部放入到字典中 22 23 self.write(dict) 24 25 class HomeHandler(tornado.web.RequestHandler): 26 def get(self): 27 self.render("home.html") 28 29 def post(self): 30 obj = IndexForm() 31 is_valid,value_dict = obj.check_valid(self) 32 print(is_valid) 33 34 #如果全部验证成功,将用胡俗人的数据全部放入到字典中 35 36 self.write(dict) 37 38 39 class BaseForm(object): 40 def check_valid(self, handle): 41 flag = True 42 value_dict = {} 43 # 获取当前类的属性字典 44 form_dict = self.__dict__ 45 46 for key, regular in form_dict.items(): 47 # 获取用户输入的数据 48 input_value = handle.get_argument(key) 49 50 # 让提交的数据 和 定义的正则表达式进行匹配 match表示从头到尾匹配 51 ret = re.match(regular, input_value) 52 # 匹配成功ret为返回的一个对象,匹配不成功返回none 53 print(key, ret, input_value) 54 55 if not ret: 56 flag = False 57 value_dict[key] = input_value 58 return flag, value_dict 59 60 class IndexForm(BaseForm): 61 def __init__(self): 62 self.host = "(.*)" 63 self.ip = "^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$" 64 self.port = '(\d+)' 65 self.phone = '^1[3|4|5|8][0-9]\d{8}$' 66 67 class HomeForm(object): 68 def __init__(self): 69 self.host = "(.*)" 70 self.ip = "^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$" 71 72 73 settings = { 74 'template_path': 'views', 75 'static_path': 'statics', 76 'static_url_prefix': '/static/', 77 'cookie_secret': 'aiuasdhflashjdfoiuashdfiuh', 78 'login_url': '/login' 79 } 80 81 application = tornado.web.Application([ 82 (r"/index", IndexHandler), 83 (r"/home", HomeHandler), 84 ], **settings) 85 86 if __name__ == "__main__": 87 application.listen(8880) 88 tornado.ioloop.IOLoop.instance().start()
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import tornado.ioloop 5 import tornado.web 6 from hashlib import sha1 7 import os, time 8 import re 9 10 11 class IPField: 12 #静态字段 13 REGULAR = "^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$" 14 def __init__(self, error_msg_dict=None, required=True): 15 self.error_msg = {} # {'required': 'IP不能为空', 'valid': 'IP格式错误'} 16 #如果用户传递的错误信息不给空,将用户的信息更新到字典中,否则使用默认的错误信息 17 if error_msg_dict: 18 self.error_msg.update(error_msg_dict) 19 self.required = required 20 self.error = None #错误信息 21 self.is_valid = False #判定格式是否满足 22 self.value = None #如果匹配成功值是多少 23 24 25 def validate(self, name, input_value): 26 """ 27 :param name: 字段名称 28 :param input_value: 表单输入内容 29 :return: 30 """ 31 if not self.required: 32 self.is_valid = True 33 self.value = input_value 34 else: 35 if not input_value.strip(): #用户输入为空 36 if self.error_msg.get('required', None): #得到错误信息 37 self.error = self.error_msg['required'] #如果不为空,用户传递的默认信息 38 else: 39 self.error = "%s is required" % name #如果为空,使用系统的默认信息 40 else: 41 ret = re.match(self.REGULAR, input_value) 42 if ret: #如果匹配 43 self.id_valid = True 44 self.value = input_value 45 else: 46 if self.error_msg.get('valid', None): 47 self.error = self.error_msg['valid'] 48 else: 49 self.error = "%s is invalid" % name 50 51 52 class IndexHandler(tornado.web.RequestHandler): 53 def get(self): 54 self.render("index.html") 55 56 def post(self): 57 obj = IndexForm() 58 is_valid,value_dict = obj.check_valid(self) 59 print(is_valid) 60 61 #如果全部验证成功,将用胡俗人的数据全部放入到字典中 62 63 self.write(dict) 64 65 class HomeHandler(tornado.web.RequestHandler): 66 def get(self): 67 error_value_dict = {} 68 self.render("home.html",error_dict = error_value_dict) 69 70 def post(self): 71 obj = HomeForm() 72 is_valid,success_value_dict,error_value_dict = obj.check_valid(self) 73 print(is_valid) 74 if is_valid: 75 for k,v in success_value_dict.items(): 76 print(k,v) 77 else: 78 for k,v in error_value_dict.items(): 79 print(k,v) 80 81 self.render("home.html",error_dict = error_value_dict) 82 83 #如果全部验证成功,将用胡俗人的数据全部放入到字典中 84 85 86 87 class BaseForm(object): 88 def check_valid(self, handle): 89 flag = True 90 value_dict = {} 91 error_message_dict ={} 92 success_value_dict = {} 93 # 获取当前类的属性字典 94 form_dict = self.__dict__ 95 for key, regular in form_dict.items(): 96 #key ip 97 #handle HomeIndex... 98 #reguler:IPField(required =true) 99 #在homeform继承baseform的时候,传递的regular是一个IPFiled的对象 100 101 input_value = handle.get_argument(key) 102 103 #IPFiled中进行验证 104 regular.validate(key,input_value) 105 if regular.is_valid: 106 success_value_dict[key]=regular.value 107 pass 108 else: 109 error_message_dict[key] = regular.error 110 flag = False 111 112 return flag, success_value_dict,error_message_dict 113 114 class IndexForm(BaseForm): 115 def __init__(self): 116 self.host = "(.*)" 117 self.ip = "^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$" 118 self.port = '(\d+)' 119 self.phone = '^1[3|4|5|8][0-9]\d{8}$' 120 121 class HomeForm(BaseForm): 122 def __init__(self): 123 self.ip = IPField(required=True,error_msg_dict = {"required":"不可为空","valid":"格式错误"}) 124 125 126 127 settings = { 128 'template_path': 'views', 129 'static_path': 'statics', 130 'static_url_prefix': '/static/', 131 'cookie_secret': 'aiuasdhflashjdfoiuashdfiuh', 132 'login_url': '/login' 133 } 134 135 application = tornado.web.Application([ 136 (r"/index", IndexHandler), 137 (r"/home", HomeHandler), 138 ], **settings) 139 140 if __name__ == "__main__": 141 application.listen(8880) 142 tornado.ioloop.IOLoop.instance().start()
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import tornado.ioloop 5 import tornado.web 6 from hashlib import sha1 7 import os, time 8 import re 9 10 11 class IPField: 12 #静态字段 13 REGULAR = "^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$" 14 def __init__(self, error_msg_dict=None, required=True): 15 self.error_msg = {} # {'required': 'IP不能为空', 'valid': 'IP格式错误'} 16 #如果用户传递的错误信息不给空,将用户的信息更新到字典中,否则使用默认的错误信息 17 if error_msg_dict: 18 self.error_msg.update(error_msg_dict) 19 self.required = required 20 self.error = None #错误信息 21 self.is_valid = False #判定格式是否满足 22 self.value = None #如果匹配成功值是多少 23 24 25 def validate(self, name, input_value): 26 """ 27 :param name: 字段名称 28 :param input_value: 表单输入内容 29 :return: 30 """ 31 32 print('ffffff',name,input_value) 33 if not self.required: 34 self.is_valid = True 35 self.value = input_value 36 else: 37 if not input_value.strip(): #用户输入为空 38 if self.error_msg.get('required', None): #得到错误信息 39 self.error = self.error_msg['required'] #如果不为空,用户传递的默认信息 40 else: 41 self.error = "%s is required" % name #如果为空,使用系统的默认信息 42 else: 43 ret = re.match(self.REGULAR, input_value) 44 if ret: #如果匹配 45 self.is_valid = True 46 self.value = input_value 47 print("匹配",self.value) 48 49 50 else: 51 52 print("不匹配") 53 if self.error_msg.get('valid', None): 54 self.error = self.error_msg['valid'] 55 else: 56 self.error = "%s is invalid" % name 57 58 59 class StringField: 60 #静态字段 61 REGULAR = "^(.*)$" 62 def __init__(self, error_msg_dict=None, required=True): 63 self.error_msg = {} # {'required': 'IP不能为空', 'valid': 'IP格式错误'} 64 #如果用户传递的错误信息不给空,将用户的信息更新到字典中,否则使用默认的错误信息 65 if error_msg_dict: 66 self.error_msg.update(error_msg_dict) 67 self.required = required 68 self.error = None #错误信息 69 self.is_valid = False #判定格式是否满足 70 self.value = None #如果匹配成功值是多少 71 72 73 def validate(self, name, input_value): 74 """ 75 :param name: 字段名称 76 :param input_value: 表单输入内容 77 :return: 78 """ 79 if not self.required: 80 self.is_valid = True 81 self.value = input_value 82 else: 83 if not input_value.strip(): #用户输入为空 84 if self.error_msg.get('required', None): #得到错误信息 85 self.error = self.error_msg['required'] #如果不为空,用户传递的默认信息 86 else: 87 self.error = "%s is required" % name #如果为空,使用系统的默认信息 88 else: 89 ret = re.match(self.REGULAR, input_value) 90 if ret: #如果匹配 91 self.is_valid = True 92 self.value = input_value 93 else: 94 if self.error_msg.get('valid', None): 95 self.error = self.error_msg['valid'] 96 else: 97 self.error = "%s is invalid" % name 98 99 100 class CheckboxField: 101 #checkbox 验证没有值即可 102 def __init__(self, error_msg_dict=None, required=True): 103 self.error_msg = {} # {'required': 'IP不能为空', 'valid': 'IP格式错误'} 104 #如果用户传递的错误信息不给空,将用户的信息更新到字典中,否则使用默认的错误信息 105 if error_msg_dict: 106 self.error_msg.update(error_msg_dict) 107 self.required = required 108 self.error = None #错误信息 109 self.is_valid = False #判定格式是否满足 110 self.value = None #如果匹配成功值是多少 111 112 113 def validate(self, name, input_value): 114 """ 115 :param name: 字段名称favor 116 :param input_value: 表单输入内容 117 :return: 118 """ 119 print(name,input_value) 120 if not self.required: 121 self.is_valid = True 122 self.value = input_value 123 else: 124 if not input_value: #用户输入为空 125 if self.error_msg.get('required', None): #得到错误信息 126 self.error = self.error_msg['required'] #如果不为空,用户传递的默认信息 127 else: 128 self.error = "%s is required" % name #如果为空,使用系统的默认信息 129 else: 130 self.is_valid = True 131 self.value = input_value 132 print(name,self.value) 133 134 class IndexHandler(tornado.web.RequestHandler): 135 def get(self): 136 self.render("index.html") 137 138 def post(self): 139 obj = IndexForm() 140 is_valid,value_dict = obj.check_valid(self) 141 print(is_valid) 142 143 #如果全部验证成功,将用胡俗人的数据全部放入到字典中 144 145 self.write(dict) 146 147 class HomeHandler(tornado.web.RequestHandler): 148 def get(self): 149 error_value_dict = {} 150 self.render("home.html",error_dict = error_value_dict) 151 152 def post(self): 153 obj = HomeForm() 154 is_valid,success_value_dict,error_value_dict = obj.check_valid(self) 155 print('aabb',is_valid) 156 if is_valid: 157 for k,v in success_value_dict.items(): 158 print(k,v) 159 else: 160 for k,v in error_value_dict.items(): 161 print(k,v) 162 163 self.render("home.html",error_dict = error_value_dict) 164 165 #如果全部验证成功,将用胡俗人的数据全部放入到字典中 166 167 168 169 class BaseForm(object): 170 def check_valid(self, handle): 171 flag = True 172 value_dict = {} 173 error_message_dict ={} 174 success_value_dict = {} 175 # 获取当前类的属性字典 176 form_dict = self.__dict__ 177 for key, regular in form_dict.items(): 178 #key ip 179 #handle HomeIndex... 180 #reguler:IPField(required =true) 181 #在homeform继承baseform的时候,传递的regular是一个IPFiled的对象 182 if type(regular) == CheckboxField: 183 #传递过来的regular 是一个对象 184 input_value = handle.get_arguments(key) 185 186 print(input_value, 'aaaaaa'); 187 else: 188 input_value = handle.get_argument(key) 189 190 #IPFiled中进行验证 191 regular.validate(key,input_value) 192 193 if regular.is_valid: 194 success_value_dict[key]=regular.value 195 196 print('regular.value',regular.value) 197 198 else: 199 error_message_dict[key] = regular.error 200 flag = False 201 202 203 for a,d in success_value_dict.items(): 204 print(a,d) 205 206 for a, d in error_message_dict.items(): 207 print(a, d) 208 209 return flag, success_value_dict,error_message_dict 210 211 class IndexForm(BaseForm): 212 def __init__(self): 213 self.host = "(.*)" 214 self.ip = "^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$" 215 self.port = '(\d+)' 216 self.phone = '^1[3|4|5|8][0-9]\d{8}$' 217 218 class HomeForm(BaseForm): 219 def __init__(self): 220 self.ip = IPField(required=True,error_msg_dict = {"required":"不可为空","valid":"格式错误"}) 221 # self.host = StringField(required=True) 222 self.favor = CheckboxField(required=True) 223 224 225 settings = { 226 'template_path': 'views', 227 'static_path': 'statics', 228 'static_url_prefix': '/static/', 229 'cookie_secret': 'aiuasdhflashjdfoiuashdfiuh', 230 'login_url': '/login' 231 } 232 233 application = tornado.web.Application([ 234 (r"/index", IndexHandler), 235 (r"/home", HomeHandler), 236 ], **settings) 237 238 if __name__ == "__main__": 239 application.listen(8880) 240 tornado.ioloop.IOLoop.instance().start()
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import tornado.ioloop 5 import tornado.web 6 from hashlib import sha1 7 import os, time 8 import re 9 10 11 class IPField: 12 #静态字段 13 REGULAR = "^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$" 14 def __init__(self, error_msg_dict=None, required=True): 15 self.error_msg = {} # {'required': 'IP不能为空', 'valid': 'IP格式错误'} 16 #如果用户传递的错误信息不给空,将用户的信息更新到字典中,否则使用默认的错误信息 17 if error_msg_dict: 18 self.error_msg.update(error_msg_dict) 19 self.required = required 20 self.error = None #错误信息 21 self.is_valid = False #判定格式是否满足 22 self.value = None #如果匹配成功值是多少 23 24 25 def validate(self, name, input_value): 26 """ 27 :param name: 字段名称 28 :param input_value: 表单输入内容 29 :return: 30 """ 31 32 print('ffffff',name,input_value) 33 if not self.required: 34 self.is_valid = True 35 self.value = input_value 36 else: 37 if not input_value.strip(): #用户输入为空 38 if self.error_msg.get('required', None): #得到错误信息 39 self.error = self.error_msg['required'] #如果不为空,用户传递的默认信息 40 else: 41 self.error = "%s is required" % name #如果为空,使用系统的默认信息 42 else: 43 ret = re.match(self.REGULAR, input_value) 44 if ret: #如果匹配 45 self.is_valid = True 46 self.value = input_value 47 print("匹配",self.value) 48 49 50 else: 51 52 print("不匹配") 53 if self.error_msg.get('valid', None): 54 self.error = self.error_msg['valid'] 55 else: 56 self.error = "%s is invalid" % name 57 58 59 class StringField: 60 #静态字段 61 REGULAR = "^(.*)$" 62 def __init__(self, error_msg_dict=None, required=True): 63 self.error_msg = {} # {'required': 'IP不能为空', 'valid': 'IP格式错误'} 64 #如果用户传递的错误信息不给空,将用户的信息更新到字典中,否则使用默认的错误信息 65 if error_msg_dict: 66 self.error_msg.update(error_msg_dict) 67 self.required = required 68 self.error = None #错误信息 69 self.is_valid = False #判定格式是否满足 70 self.value = None #如果匹配成功值是多少 71 72 73 def validate(self, name, input_value): 74 """ 75 :param name: 字段名称 76 :param input_value: 表单输入内容 77 :return: 78 """ 79 if not self.required: 80 self.is_valid = True 81 self.value = input_value 82 else: 83 if not input_value.strip(): #用户输入为空 84 if self.error_msg.get('required', None): #得到错误信息 85 self.error = self.error_msg['required'] #如果不为空,用户传递的默认信息 86 else: 87 self.error = "%s is required" % name #如果为空,使用系统的默认信息 88 else: 89 ret = re.match(self.REGULAR, input_value) 90 if ret: #如果匹配 91 self.is_valid = True 92 self.value = input_value 93 else: 94 if self.error_msg.get('valid', None): 95 self.error = self.error_msg['valid'] 96 else: 97 self.error = "%s is invalid" % name 98 99 100 class CheckboxField: 101 #checkbox 验证没有值即可 102 def __init__(self, error_msg_dict=None, required=True): 103 self.error_msg = {} # {'required': 'IP不能为空', 'valid': 'IP格式错误'} 104 #如果用户传递的错误信息不给空,将用户的信息更新到字典中,否则使用默认的错误信息 105 if error_msg_dict: 106 self.error_msg.update(error_msg_dict) 107 self.required = required 108 self.error = None #错误信息 109 self.is_valid = False #判定格式是否满足 110 self.value = None #如果匹配成功值是多少 111 112 113 def validate(self, name, input_value): 114 """ 115 :param name: 字段名称favor 116 :param input_value: 表单输入内容 117 :return: 118 """ 119 print(name,input_value) 120 if not self.required: 121 self.is_valid = True 122 self.value = input_value 123 else: 124 if not input_value: #用户输入为空 125 if self.error_msg.get('required', None): #得到错误信息 126 self.error = self.error_msg['required'] #如果不为空,用户传递的默认信息 127 else: 128 self.error = "%s is required" % name #如果为空,使用系统的默认信息 129 else: 130 self.is_valid = True 131 self.value = input_value 132 print(name,self.value) 133 134 135 class FileField: 136 REGULAR = "^(\w+\.pdf)|(\w+\.mp3)|(\w+\.py)$" 137 #checkbox 验证没有值即可 138 def __init__(self, error_msg_dict=None, required=True): 139 self.error_msg = {} # {'required': 'IP不能为空', 'valid': 'IP格式错误'} 140 #如果用户传递的错误信息不给空,将用户的信息更新到字典中,否则使用默认的错误信息 141 if error_msg_dict: 142 self.error_msg.update(error_msg_dict) 143 self.required = required 144 self.error = None #错误信息 145 self.is_valid = True #判定格式是否满足 146 self.value = None #如果匹配成功值是多少 147 self.name = None 148 self.success_file_name_list =[] 149 150 151 def validate(self, name, all_file_name_list): 152 """ 153 :param name: 字段名称favor 154 :param all_file_name_list: 所有文件的文件名称 155 :return: 156 """ 157 self.name = name 158 print(name,all_file_name_list) 159 if not self.required: 160 self.is_valid = True 161 self.success_file_name_list = all_file_name_list 162 else: 163 164 for file_name in all_file_name_list: 165 ret = re.match(FileField.REGULAR, file_name) 166 if not ret: # 如果bu 匹配 167 self.is_valid = False 168 print("aaaaaaaa",self.is_valid) 169 if self.error_dict.get("valid",None): 170 self.error = self.error_dict["valid"] 171 else: 172 self.error = "%s is invalid" % name 173 break; 174 175 else: 176 177 self.success_file_name_list.append(file_name) 178 179 print("bbbbbbbbbb", self.is_valid) 180 181 self.value = self.success_file_name_list 182 183 184 185 def save(self, request, path=None): 186 file_metas = request.files.get(self.name) #name 指的是 fafafa 187 for meta in file_metas: 188 file_name = meta['filename'] 189 new_file_name = os.path.join(path,file_name) 190 if file_name and file_name in self.value: 191 192 with open(new_file_name, 'wb') as up: 193 up.write(meta['body']) 194 195 196 class IndexHandler(tornado.web.RequestHandler): 197 def get(self): 198 self.render("index.html") 199 200 def post(self): 201 obj = IndexForm() 202 is_valid,value_dict = obj.check_valid(self) 203 print(is_valid) 204 205 #如果全部验证成功,将用胡俗人的数据全部放入到字典中 206 207 self.write(dict) 208 209 class HomeHandler(tornado.web.RequestHandler): 210 def get(self): 211 error_value_dict = {} 212 self.render("home.html",error_dict = error_value_dict) 213 214 def post(self): 215 obj = HomeForm() 216 is_valid,success_value_dict,error_value_dict = obj.check_valid(self) 217 print('aabb',is_valid) 218 if is_valid: 219 for k,v in success_value_dict.items(): 220 print(k,v) 221 222 obj.fafafa.save(self.request,'statics') 223 else: 224 for k,v in error_value_dict.items(): 225 print(k,v) 226 227 self.render("home.html",error_dict = error_value_dict) 228 229 #如果全部验证成功,将用胡俗人的数据全部放入到字典中 230 231 232 233 class BaseForm(object): 234 def check_valid(self, handle): 235 flag = True 236 value_dict = {} 237 error_message_dict ={} 238 success_value_dict = {} 239 # 获取当前类的属性字典 240 form_dict = self.__dict__ 241 for key, regular in form_dict.items(): 242 #key ip 243 #handle HomeIndex... 244 #reguler:IPField(required =true) 245 #在homeform继承baseform的时候,传递的regular是一个IPFiled的对象 246 if type(regular) == CheckboxField: 247 #传递过来的regular 是一个对象 248 input_value = handle.get_arguments(key) 249 250 if type(regular) == FileField: 251 # 获得文件名称 252 file_list = handle.request.files.get(key) 253 print('file_list',file_list) 254 #file list 结构 [{"body":xxxx,"filename":xxx}] 255 256 file_name_list = [] 257 for item in file_list: 258 file_name_list.append(item["filename"]) 259 #对所有文件名称进行验证 260 261 input_value = file_name_list 262 263 else: 264 input_value = handle.get_argument(key) 265 266 #IPFiled中进行验证 267 regular.validate(key,input_value) 268 269 if regular.is_valid: 270 success_value_dict[key]=regular.value 271 272 print('regular.value',regular.value) 273 274 else: 275 error_message_dict[key] = regular.error 276 flag = False 277 278 279 for a,d in success_value_dict.items(): 280 print(a,d) 281 282 for a, d in error_message_dict.items(): 283 print(a, d) 284 285 return flag, success_value_dict,error_message_dict 286 287 class IndexForm(BaseForm): 288 def __init__(self): 289 self.host = "(.*)" 290 self.ip = "^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$" 291 self.port = '(\d+)' 292 self.phone = '^1[3|4|5|8][0-9]\d{8}$' 293 294 class HomeForm(BaseForm): 295 def __init__(self): 296 # self.ip = IPField(required=True,error_msg_dict = {"required":"不可为空","valid":"格式错误"}) 297 # self.host = StringField(required=True) 298 # self.favor = CheckboxField(required=True) 299 self.fafafa = FileField(required=True) 300 301 302 settings = { 303 'template_path': 'views', 304 'static_path': 'statics', 305 'static_url_prefix': '/static/', 306 'cookie_secret': 'aiuasdhflashjdfoiuashdfiuh', 307 'login_url': '/login' 308 } 309 310 application = tornado.web.Application([ 311 (r"/index", IndexHandler), 312 (r"/home", HomeHandler), 313 ], **settings) 314 315 if __name__ == "__main__": 316 application.listen(8880) 317 tornado.ioloop.IOLoop.instance().start()
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import tornado.ioloop 5 import tornado.web 6 from hashlib import sha1 7 import os, time 8 import re 9 10 11 class IPField: 12 #静态字段 13 REGULAR = "^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$" 14 def __init__(self, error_msg_dict=None, required=True): 15 self.error_msg = {} # {'required': 'IP不能为空', 'valid': 'IP格式错误'} 16 #如果用户传递的错误信息不给空,将用户的信息更新到字典中,否则使用默认的错误信息 17 if error_msg_dict: 18 self.error_msg.update(error_msg_dict) 19 self.required = required 20 self.error = None #错误信息 21 self.is_valid = False #判定格式是否满足 22 self.value = None #如果匹配成功值是多少 23 24 25 def validate(self, name, input_value): 26 """ 27 :param name: 字段名称 28 :param input_value: 表单输入内容 29 :return: 30 """ 31 32 print('ffffff',name,input_value) 33 if not self.required: 34 self.is_valid = True 35 self.value = input_value 36 else: 37 if not input_value.strip(): #用户输入为空 38 if self.error_msg.get('required', None): #得到错误信息 39 self.error = self.error_msg['required'] #如果不为空,用户传递的默认信息 40 else: 41 self.error = "%s is required" % name #如果为空,使用系统的默认信息 42 else: 43 ret = re.match(self.REGULAR, input_value) 44 if ret: #如果匹配 45 self.is_valid = True 46 self.value = input_value 47 print("匹配",self.value) 48 49 50 else: 51 52 print("不匹配") 53 if self.error_msg.get('valid', None): 54 self.error = self.error_msg['valid'] 55 else: 56 self.error = "%s is invalid" % name 57 58 59 class StringField: 60 #静态字段 61 REGULAR = "^(.*)$" 62 def __init__(self, error_msg_dict=None, required=True): 63 self.error_msg = {} # {'required': 'IP不能为空', 'valid': 'IP格式错误'} 64 #如果用户传递的错误信息不给空,将用户的信息更新到字典中,否则使用默认的错误信息 65 if error_msg_dict: 66 self.error_msg.update(error_msg_dict) 67 self.required = required 68 self.error = None #错误信息 69 self.is_valid = False #判定格式是否满足 70 self.value = None #如果匹配成功值是多少 71 72 73 def validate(self, name, input_value): 74 """ 75 :param name: 字段名称 76 :param input_value: 表单输入内容 77 :return: 78 """ 79 if not self.required: 80 self.is_valid = True 81 self.value = input_value 82 else: 83 if not input_value.strip(): #用户输入为空 84 if self.error_msg.get('required', None): #得到错误信息 85 self.error = self.error_msg['required'] #如果不为空,用户传递的默认信息 86 else: 87 self.error = "%s is required" % name #如果为空,使用系统的默认信息 88 else: 89 ret = re.match(self.REGULAR, input_value) 90 if ret: #如果匹配 91 self.is_valid = True 92 self.value = input_value 93 else: 94 if self.error_msg.get('valid', None): 95 self.error = self.error_msg['valid'] 96 else: 97 self.error = "%s is invalid" % name 98 99 100 class CheckboxField: 101 #checkbox 验证没有值即可 102 def __init__(self, error_msg_dict=None, required=True): 103 self.error_msg = {} # {'required': 'IP不能为空', 'valid': 'IP格式错误'} 104 #如果用户传递的错误信息不给空,将用户的信息更新到字典中,否则使用默认的错误信息 105 if error_msg_dict: 106 self.error_msg.update(error_msg_dict) 107 self.required = required 108 self.error = None #错误信息 109 self.is_valid = False #判定格式是否满足 110 self.value = None #如果匹配成功值是多少 111 112 113 def validate(self, name, input_value): 114 """ 115 :param name: 字段名称favor 116 :param input_value: 表单输入内容 117 :return: 118 """ 119 print(name,input_value) 120 if not self.required: 121 self.is_valid = True 122 self.value = input_value 123 else: 124 if not input_value: #用户输入为空 125 if self.error_msg.get('required', None): #得到错误信息 126 self.error = self.error_msg['required'] #如果不为空,用户传递的默认信息 127 else: 128 self.error = "%s is required" % name #如果为空,使用系统的默认信息 129 else: 130 self.is_valid = True 131 self.value = input_value 132 print(name,self.value) 133 134 135 class FileField: 136 REGULAR = "^(\w+\.pdf)|(\w+\.mp3)|(\w+\.py)$" 137 #checkbox 验证没有值即可 138 def __init__(self, error_msg_dict=None, required=True): 139 self.error_msg = {} # {'required': 'IP不能为空', 'valid': 'IP格式错误'} 140 #如果用户传递的错误信息不给空,将用户的信息更新到字典中,否则使用默认的错误信息 141 if error_msg_dict: 142 self.error_msg.update(error_msg_dict) 143 self.required = required 144 self.error = None #错误信息 145 self.is_valid = True #判定格式是否满足 146 self.value = None #如果匹配成功值是多少 147 self.name = None 148 self.success_file_name_list =[] 149 150 151 def validate(self, name, all_file_name_list): 152 """ 153 :param name: 字段名称favor 154 :param all_file_name_list: 所有文件的文件名称 155 :return: 156 """ 157 self.name = name 158 print(name,all_file_name_list) 159 if not self.required: 160 self.is_valid = True 161 self.success_file_name_list = all_file_name_list 162 else: 163 164 for file_name in all_file_name_list: 165 ret = re.match(FileField.REGULAR, file_name) 166 if not ret: # 如果bu 匹配 167 self.is_valid = False 168 print("aaaaaaaa",self.is_valid) 169 if self.error_dict.get("valid",None): 170 self.error = self.error_dict["valid"] 171 else: 172 self.error = "%s is invalid" % name 173 break; 174 175 else: 176 177 self.success_file_name_list.append(file_name) 178 179 print("bbbbbbbbbb", self.is_valid) 180 181 self.value = self.success_file_name_list 182 183 184 185 def save(self, request, path=None): 186 file_metas = request.files.get(self.name) #name 指的是 fafafa 187 for meta in file_metas: 188 file_name = meta['filename'] 189 new_file_name = os.path.join(path,file_name) 190 if file_name and file_name in self.value: 191 192 with open(new_file_name, 'wb') as up: 193 up.write(meta['body']) 194 195 196 class IndexHandler(tornado.web.RequestHandler): 197 def get(self): 198 self.render("index.html") 199 200 def post(self): 201 obj = IndexForm() 202 is_valid,value_dict = obj.check_valid(self) 203 print(is_valid) 204 205 #如果全部验证成功,将用胡俗人的数据全部放入到字典中 206 207 self.write(dict) 208 209 class HomeHandler(tornado.web.RequestHandler): 210 def get(self): 211 error_value_dict = {} 212 self.render("home.html",error_dict = error_value_dict) 213 214 def post(self): 215 obj = HomeForm() 216 is_valid,success_value_dict,error_value_dict = obj.check_valid(self) 217 print('aabb',is_valid) 218 if is_valid: 219 for k,v in success_value_dict.items(): 220 print(k,v) 221 222 obj.fafafa.save(self.request,'statics') 223 else: 224 for k,v in error_value_dict.items(): 225 print(k,v) 226 227 self.render("home.html",error_dict = error_value_dict) 228 229 #如果全部验证成功,将用胡俗人的数据全部放入到字典中 230 231 232 233 class BaseForm(object): 234 def check_valid(self, handle): 235 flag = True 236 value_dict = {} 237 error_message_dict ={} 238 success_value_dict = {} 239 # 获取当前类的属性字典 240 form_dict = self.__dict__ 241 for key, regular in form_dict.items(): 242 #key ip 243 #handle HomeIndex... 244 #reguler:IPField(required =true) 245 #在homeform继承baseform的时候,传递的regular是一个IPFiled的对象 246 if type(regular) == CheckboxField: 247 #传递过来的regular 是一个对象 248 input_value = handle.get_arguments(key) 249 250 if type(regular) == FileField: 251 # 获得文件名称 252 file_list = handle.request.files.get(key) 253 print('file_list',file_list) 254 #file list 结构 [{"body":xxxx,"filename":xxx}] 255 256 file_name_list = [] 257 for item in file_list: 258 file_name_list.append(item["filename"]) 259 #对所有文件名称进行验证 260 261 input_value = file_name_list 262 263 else: 264 input_value = handle.get_argument(key) 265 266 #IPFiled中进行验证 267 regular.validate(key,input_value) 268 269 if regular.is_valid: 270 success_value_dict[key]=regular.value 271 272 print('regular.value',regular.value) 273 274 else: 275 error_message_dict[key] = regular.error 276 flag = False 277 278 279 for a,d in success_value_dict.items(): 280 print(a,d) 281 282 for a, d in error_message_dict.items(): 283 print(a, d) 284 285 return flag, success_value_dict,error_message_dict 286 287 class IndexForm(BaseForm): 288 def __init__(self): 289 self.host = "(.*)" 290 self.ip = "^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$" 291 self.port = '(\d+)' 292 self.phone = '^1[3|4|5|8][0-9]\d{8}$' 293 294 class HomeForm(BaseForm): 295 def __init__(self): 296 # self.ip = IPField(required=True,error_msg_dict = {"required":"不可为空","valid":"格式错误"}) 297 # self.host = StringField(required=True) 298 # self.favor = CheckboxField(required=True) 299 self.fafafa = FileField(required=True) 300 301 302 settings = { 303 'template_path': 'views', 304 'static_path': 'statics', 305 'static_url_prefix': '/static/', 306 'cookie_secret': 'aiuasdhflashjdfoiuashdfiuh', 307 'login_url': '/login' 308 } 309 310 application = tornado.web.Application([ 311 (r"/index", IndexHandler), 312 (r"/home", HomeHandler), 313 ], **settings) 314 315 if __name__ == "__main__": 316 application.listen(8880) 317 tornado.ioloop.IOLoop.instance().start()
抽屉练习
使用了bootstrap 控件实现了模态框体
内容包括登录、发帖
redirect('/index/') 跳转到index
1 <!DOCTYPE html> 2 <html> 3 <head lang="en"> 4 <meta charset="UTF-8"> 5 <title>抽屉新热榜</title> 6 <link rel="stylesheet" href="{{static_url('css/commons.css')}}" /> 7 <link rel="stylesheet" href="{{static_url('plugins/bootstrap/css/bootstrap.css')}}" /> 8 9 </head> 10 <body> 11 <div class="pg-header"> 12 <div class="w"> 13 <a class="logo" href="/"></a> 14 <div class="act-menu"> 15 <a href="/all/hot/recent/1" class="tb active">全部</a> 16 <a href="/all/hot/recent/1" class="tb">42区</a> 17 <a href="/all/hot/recent/1" class="tb">段子</a> 18 <a href="/all/hot/recent/1" class="tb">图片</a> 19 <a href="/all/hot/recent/1" class="tb">挨踢1024</a> 20 <a href="/all/hot/recent/1" class="tb">你问我答</a> 21 </div> 22 <div class="key-sera"> 23 24 <form action="/search/show" method="post" name="searchFrm2" id="searchFrm2"> 25 <input type="text" class="search-txt-s" name="words" id="txtSearch2" autocomplete="off"> 26 27 <a href="javascript:;" class="i" name="searchBtn_2" id="searchBtn_3"><span class="ico"></span></a> 28 <input type="hidden" value="1" id="page" name="page"> 29 </form> 30 31 </div> 32 33 <div class="action-nav"> 34 <a href="/show/flow/1" style="float:left;position:relative;" id="btnDtaiShw">动态 35 <b class="notice-num-title" id="Dtai-num-title" style="right: 3px; display: none;"> 36 <em id="Dtai-em"></em> 37 </b> 38 </a> 39 <a href="javascript:;" id="btnNotShw" class="notice-box">通知 40 <b class="notice-num-title" id="notice-num-title" style="display: none;"> 41 <em id="notice-em"></em> 42 <i>+</i> 43 </b> 44 </a> 45 {% if user_info["is_login"] %} 46 <a href="/user/link/saved/1" id="loginUserNc" class="userPro-Box"> 47 <img src="http://img2.chouti.com/CHOUTI_05B313F703D34646848BCC5571510683_W148H148=30x30).jpg" id="userProImg"> 48 <span class="u-nick" id="userProNick">{{ user_info["username"] }}</span> 49 <em id="userProArr"></em> 50 </a> 51 52 {% else %} 53 <a onclick="Login();"> 登录</a> 54 <a> 注册</a> 55 {% end %} 56 </div> 57 <div class="user-opr-box" id="userOprBox" style="left: 869px; display: none;"> 58 <a href="/user/link/saved/1" style="border-top:0;">我的新热榜</a> 59 <a href="/profile">设置</a> 60 <a class="logout" href="javascript:;">退出</a> 61 <a href="http://www.chouti.com/cdu_45792645155" target="_blank" class="ie6-a">我的收藏</a> 62 </div> 63 </div> 64 </div> 65 66 67 68 69 <div class="pg-body"> 70 71 <div style="background-color: #eee;"> 72 <div class="w body-content"> 73 <div class="clearfix"> 74 <div class="content-l" > 75 <div class="nav-top-area"> 76 <div class="child-nav"> 77 <!-- 当不是全部页面时 --> 78 <a href="/r/pic/hot/1" hidefocus="false" class="icons active hotbtn" id="hotts-nav-btn">最热</a> 79 <a href="/r/pic/new/1" hidefocus="false" class="newbtn" id="newest-nav-btn">最新</a> 80 <!-- 当是全部页面时 --> 81 </div> 82 <!-- 当是全部页面时 --> 83 <a href="javascript:void(0);" onclick="Publish();" class="publish-btn" id="publishBtn" lang="pic"> 84 <span class="ico n1"></span><span class="n2" >发布的</span> 85 </a> 86 87 88 89 </div> 90 91 92 <div class="content-list" id="content_list"> 93 94 {% for new in new_list%} 95 96 <div class="item"> 97 98 <div class="timeIntoPool">1458285240218000,1458288835879000</div> 99 100 <div class="null-item"></div> 101 102 <div class="news-content" id="newsContent8118680"> 103 <div class="part1"> 104 <a href="http://wallstreetcn.com/node/232597" class="show-content" target="_blank" onmousedown="linksClickStat(8118680);">{{new["title"]}}</a> 105 <span class="content-source">-wallstreetcn.com</span> 106 <!-- 段子和谣言类别不显示类别名称 --> 107 <a href="/r/news/hot/1" class="n2"><span class="content-kind">42区</span></a> 108 <!-- 来源手机客户端 --> 109 <!-- 显示话题标签 --> 110 </div> 111 <!-- 显示摘要 --> 112 <div class="area-summary"> 113 <span class="summary">{{new["content"]}}</span> 114 </div> 115 <div class="part2" share-pic="http://img2.chouti.com/CHOUTI_AD764B84163A4A8093C2BF54CEAA4AAB_W400H266.jpg" share-title="进入调整期?深圳二手房成交较年初锐减30%" share-summary="多家中介数据显示,深圳3月二手房成交量比1月下降超过30%,新房成交量同样出现下降。分析称,政策收紧预期较大程度上影响了市场成交,而业主方多看好后市,双方存在一定博弈。预计4月评估价调整政策落地后,二手房市场或进入短暂调整期。" share-linkid="8118680" share-subject="42区"> 116 <a href="javascript:;" class="digg-a" title="推荐"><span class="hand-icon icon-digg"></span><b>7</b><i style="display:none">8118680</i></a> 117 <a href="javascript:;" class="discus-a" id="discus-a-8118680" lang="8118680" title=""><span class="hand-icon icon-discus"></span><b>4</b></a> 118 <a href="javascript:;" class="collect-a" id="collect-a-8118680" lang="8118680" title="加入私藏" destjid="cdu_45792645155" jid="chouti150326"><span class="hand-icon icon-collect"></span><b>私藏</b></a> 119 <span class="left time-into"><a class="time-a" href="/link/8118680" target="_blank"><b>1小时18分钟前</b></a><i>入热榜</i></span> 120 <!-- 分享各微博的按钮 --> 121 122 <span class="share-site-to" style="visibility: hidden;"><i>分享到</i><span class="share-icon"><a class="icon-sina" id="icon-sina" title="分享到新浪微博" href="javascript:;" hidefocus="true"></a><a class="icon-douban" id="icon-douban" title="分享到豆瓣" href="javascript:;" hidefocus="true"></a><a class="icon-qqzone" id="icon-qqzone" title="分享到QQ空间" href="javascript:;" hidefocus="true"></a><a class="icon-tenxun" id="icon-tenxun" title="分享到腾讯微博" href="javascript:;" hidefocus="true"></a><a class="icon-renren" id="icon-renren" title="分享到人人网" href="javascript:;" hidefocus="true"></a><a class="share-none"> </a></span></span></div> 123 <!-- 评论区域 --> 124 </div> 125 126 </div> 127 128 {% end %} 129 </div> 130 </div> 131 <div class="content-r"> 132 133 </div> 134 </div> 135 </div> 136 </div> 137 138 </div> 139 140 141 <div class="modal fade" id="login" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"> 142 <div class="modal-dialog" role="document"> 143 <div class="modal-content"> 144 <div class="modal-header"> 145 <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> 146 <h4 class="modal-title" id="exampleModalLabel">用户登录</h4> 147 </div> 148 <form action="/login/" method = "post"> 149 <div class="modal-body"> 150 151 <div class="form-group"> 152 <label class="control-label">用户名</label> 153 <input type="text" class="form-control" name = "username"> 154 </div> 155 <div class="form-group"> 156 <label class="control-label">密码:</label> 157 <input type="password" class="form-control" name = "pwd"> 158 </div> 159 160 </div> 161 <div class="modal-footer"> 162 <button type="button" class="btn btn-default" data-dismiss="modal">取消</button> 163 <button type="submit" class="btn btn-primary">提交</button> 164 </div> 165 166 </form> 167 168 169 </div> 170 </div> 171 </div> 172 173 <div class="modal fade" id="pub" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"> 174 <div class="modal-dialog" role="document"> 175 <div class="modal-content"> 176 <div class="modal-header"> 177 <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> 178 <h4 class="modal-title" id="exampleModalLabe2">发帖</h4> 179 </div> 180 <form action="/publish/" method = "post"> 181 <div class="modal-body"> 182 183 <div class="form-group"> 184 <label class="control-label">标题</label> 185 <input type="text" class="form-control" name = "title"> 186 </div> 187 <div class="form-group"> 188 <label class="control-label">内容:</label> 189 <input type="input" class="form-control" name = "content"> 190 </div> 191 192 </div> 193 <div class="modal-footer"> 194 <button type="button" class="btn btn-default" data-dismiss="modal">取消</button> 195 <button type="submit" class="btn btn-primary">提交</button> 196 </div> 197 198 </form> 199 200 201 </div> 202 </div> 203 </div> 204 205 206 <script src="{{static_url('js/jquery-2.1.4.min.js')}}"></script> 207 <script src="{{static_url('plugins/bootstrap/js/bootstrap.js')}}" ></script> 208 209 <script> 210 $(function(){ 211 $('#loginUserNc,#userOprBox').mouseover(function(){ 212 $('#userOprBox').css('display', 'block'); 213 $('#loginUserNc').addClass('active'); 214 }).mouseout(function () { 215 $('#userOprBox').css('display', 'none'); 216 $('#loginUserNc').removeClass('active'); 217 }) 218 }); 219 220 221 function Login(){ 222 console.log('aaaa'); 223 $('#login').modal("show"); 224 225 } 226 227 function Publish(){ 228 console.log('aaaa'); 229 $('#pub').modal("show"); 230 231 } 232 </script> 233 </body> 234 </html>
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import tornado.ioloop 5 import tornado.web 6 7 INPUT_IST = [] 8 USER_INFO = {"is_login":None} 9 NEW_LIST = [ 10 {"title":"new帖子1","content":"今日大雨"}, 11 12 ] 13 14 class MainHandler(tornado.web.RequestHandler): 15 def get(self): 16 print("ok1") 17 self.render("index.html", list_info=[11, 22, 33]) 18 19 20 21 class LoginHandler(tornado.web.RequestHandler): 22 def get(self): 23 print("ok1") 24 self.render("index.html", list_info=[11, 22, 33]) 25 26 def post(self,*args,**kwargs): 27 user_name = self.get_argument("username",None) 28 pwd = self.get_argument("pwd",None) 29 30 if user_name == "yan" and pwd == "123": 31 USER_INFO["is_login"] = True; 32 USER_INFO["username"] = user_name; 33 USER_INFO["pwd"] = pwd 34 self.render("index.html",user_info = USER_INFO,new_list = NEW_LIST) 35 36 37 38 class PublishHandler(tornado.web.RequestHandler): 39 def get(self): 40 print("ok1") 41 self.render("index.html", list_info=[11, 22, 33]) 42 43 def post(self,*args,**kwargs): 44 45 if USER_INFO["is_login"]: 46 title= self.get_argument("title",None); 47 content = self.get_argument("content",None) 48 49 NEW_LIST.append({"title":title,"content":content}) 50 print(NEW_LIST) 51 self.redirect("/index/") 52 53 54 class IndexHandler(tornado.web.RequestHandler): 55 def get(self,*args,**kwargs): 56 self.render("index.html",user_info = USER_INFO,new_list = NEW_LIST) 57 58 settings = { 59 'template_path': 'tpl', 60 'static_path': 'static', 61 'static_url_prefix': '/static/', 62 } 63 application = tornado.web.Application([ 64 (r"/index/", IndexHandler), 65 (r"/login/", LoginHandler), 66 (r"/publish/", PublishHandler), 67 ],**settings) 68 69 if __name__ == "__main__": 70 application.listen(8888) 71 tornado.ioloop.IOLoop.instance().start()

浙公网安备 33010602011771号