Tornado学习笔记(一)51CTO博客 - 凯时娱乐

Tornado学习笔记(一)51CTO博客

2019年03月01日12时37分06秒 | 作者: 浩广 | 标签: 办法,学习,假如 | 浏览: 1626

最近开端用Tornado做开发了,究其原因,主要是Tornado根据Python,一来代码量少开发速度快,二来选用epoll办法,能够承载的并发量很高。在我的i5台式机上用ab测验,不衔接数据库的情况下,单用get生成页面,大约均匀的并发量在7900左右。这比php或许java能够承载并发量都高许多许多。三来Python代码可维护性相对来说比php好许多,语法结构明晰。四来,tornado的结构规划的很黄很暴力,以HTTP恳求办法作为办法称号,一般情况下,用户写一个页面只需求有get和post两种办法的办法界说就够了。


在学习的过程中遇到一些比较重要的问题,记载下来今后备检,在学习的过程中遇到不少问题,根本都是靠***处理,百度实在是令人痛苦不堪。记载比较零星一些,或许不只限于tornado,也会包含python的一些常识。由于我也还在学习过程中,所以有些东西不一定翔实或许了解到位,tornado高人勿拍。


tornado入门不是很难,只需了解了他处理的办法就很好做了。tornado在处理网页的时分,针关于URL的衔接,实践就是对class类的一个路由映射。而类中的办法一般无非就两种,处理衔接恳求的get或许post。所以tornado的页面编写很简单。比方,这是一个用作验证登录用户的类,逐行解释一下:

class SigninHandler(BaseHandler): #引进BaseHandler
    def post(self): #HTTP的POST办法,是GET烘托的form中的post method所对应
        username = self.get_argument(username) #获取form中username的值
        password = self.get_argument(password) #获取form中password的值
        conn = MySQLdb.connect(localhost, user = root, passwd = , db = datacenter, charset = utf8, cursorclass = MySQLdb.cursors.DictCursor) #衔接数据库,指定cursorclass的意图是要让回来成果以字典的办法呈现,假如不写,是以元组办法回来
        cursor= conn.cursor() #界说数据库指针

        sql = SELECT * FROM dc_users WHERE username=%s AND password=password(%s) #写sql,为何这样写后边再说
        cursor.execute(sql, (username, password,)) #履行SQL
        row = cursor.fetchone() #获取一条,回来值为dict,由于前面衔接数据库时界说了cursorclass = MySQLdb.cursors.DictCursor,当然,你需求import MySQLdb.cursors的包
        if row: #假如存在记载
            self.set_secure_cookie(id, str(row[id]).encode(unicode_escape),  expires_days=None) #设置安全cookie,防止xsrf跨域
            self.set_secure_cookie(username, row[username].encode(unicode_escape),  expires_days=None) #same
            self.set_secure_cookie(role, row[role].encode(unicode_escape),  expires_days=None) #same
            ip = self.request.remote_ip #获取来访者IP
            sql = UPDATE dc_users SET last_access = NOW(), last_ip=%s WHERE id = %s #认证审计改变的SQL
            cursor.execute(sql, (ip, row[id],)) #履行SQL
            conn.commit() #提交履行
            cursor.close() #封闭指针
            conn.close() #封闭数据库衔接
            self.redirect(/) #转入主页
            return #回来,依照官方文档的要求,在redirect之后需求写空的return,不然或许会有问题,实测的确会有问题
        else: #假如不存在记载
            self.redirect(/Signin) #跳转回登录页面
            return
    def get(self): #HTTP GET办法
        self.render(users/login_form.html) #烘托登录框HTML


login_form.html内容如下

{% include header.html %} <!引进header文件,需求跟login_form在同一途径下,不然写相对途径,如 {% include ../header.html %} >
<div >
    <h2><script>document.write(language.Title +   + language.Version +  -  + language.Codename)</script></h2>
    <form  method="post" action="/Signin"> <!这儿的action对应的上面Python代码中SigninHandler的post办法>
        {% module xsrf_form_html() %} <!防跨域cookie模块>
        <div >
            <label ><script>document.write(language.Username + language.Colon)</script></label>
            <div ><input  type="text" name="username" placeholder="Username"></div>
        </div>
        <div >
            <label ><script>document.write(language.Password + language.Colon)</script></label>
            <div ><input  type="password" name="password" placeholder="Password"></div>
        </div>
        <div >
            <div ></div>
            <div >
                <button type="submit" ><script>document.write(language.Signin)</script></button>
            </div>
        </div>
    </form>
</div>
{% include footer.html %}


关于主代码,应如下:

#-*- coding: utf-8 -*-

import sys
reload(sys)
sys.setdefaultencoding(utf-8)
import tornado.ioloop
import tornado.web
import tornado.httpserver
import tornado.autoreload
import os

class BaseHandler(tornado.web.RequestHandler): #BaseHandler
    def get_current_user(self):
        user = self.get_secure_cookie(username)
        return user

class IndexHandler(BaseHandler):
    @tornado.web.authenticated
    def get(self):
        if not self.current_user:
            self.redirect(/Signin) #如未登录,则跳转Signin,Signin的GET办法调用的就是login_form.html页面
            return
        self.render(welcome.html) #不然烘托welcome.html

settings = \
    {
        "cookie_secret": "HeavyMetalWillNeverDie", #Cookie secret
        "xsrf_cookies": True, #敞开跨域安全
        "gzip": False, #封闭gzip输出
        "debug": False, #封闭调试方法,其实调试方法是很纠结的一事,我喜爱翻开。
        "template_path": os.path.join(os.path.dirname(__file__), "./templates"), #界说模板,也就是login_form.html或header.html相关于本程序地点的方位
        "static_path": os.path.join(os.path.dirname(__file__), "./static"), #界说JS, CSS等文件相关于本程序地点的方位
        "login_url": "/Signin", #登录URL为/Signin
    }

application = tornado.web.Application([
    (r"/", IndexHandler), #路由设置/ 运用IndexHandler
    (r"/signin", SigninHandler) # Signin运用SigninHandler
], **settings)

if __name__  "__main__": #发动tornado,装备里假如翻开debug,则能够运用autoload,归于development方法,假如封闭debug,则不能够运用autoload,归于production方法。autoload的意义是当tornado监测到有任何文件发作改变,不需求重启server即可看到相应的页面改变,不然是修改了东西看不到改变。
    server = tornado.httpserver.HTTPServer(application)
    server.bind(10002) #绑定到10002端口
    server.start(0) #主动以多进程办法发动Tornado,不然需求手艺发动多个进程
    tornado.ioloop.IOLoop.instance().start()


关于sql部分,履行最好写成cursor.execute(sql, (id,)),将%s的东西以元组办法传递给execute办法,这样做的意图是最大程度防止SQL注入的发作。假如直接写为 select * from xxx where id = + id 或许 select * from xxx where id = %s % id 的话,会被注入。别的,假如是sqlite3的话,需求写成 select * from xxx where id=? ,然后execute办法相同。


别的,假如敞开了制止xsrf跨域功用的话,在每个HTML的form表单里有必要加上{% module xsrf_form_html() %}不然会呈现制止拜访的过错。


下篇记载一下编码格局处理,这个在python2上最厌烦。


版权声明
本文来源于网络,版权归原作者所有,其内容与观点不代表凯时娱乐立场。转载文章仅为传播更有价值的信息,如采编人员采编有误或者版权原因,请与我们联系,我们核实后立即修改或删除。

猜您喜欢的文章