Tornado总结

2019-07-06 18:10:58阅读 182评论 0

1.拆分

1)安装

(1)tornado基础包

    pip install tornado

(2)pycket包(session支持)

    pip install pycket

(3)sqlalchemy包(orm支持)

    pip install sqlalchemy

2)思路

3)文件结构

|-server.py  
|-app  
    |-__init__.py(无代码)  
    |-urls.py  
    |-configs.py  
    |-views.py  
    |-models.py  

4)文件代码

(1)server.py

    import tornado.ioloop  
    import tornado.httpserver  
    import tornado.options  
    from tornado.options import define,options  

    from app.urls import urls  
    from app.config import configs  

    define('port',type=int,default=8080)  
    #定义命令行参数,在启动服务是命令行参数如 --port=9000  

    class Myapp(tornado.web.Application):  
        def __init__(self,urls,configs):  
            super(Myapp,self).__init__(handlers=urls,**configs)  
    #重定义app  

    def make_app():  
        tornado.options.parse_command_line()  

        server=tornado.httpserver.HTTPServer(Myapp(urls,configs))  
        server.bind(options.port)  
        server.start()  

        tornado.ioloop.IOLoop.current().start()  

    if __name__=='__main__':  
        make_app()

(2)urls.py

    from tornado.web import url  

    from app import views  

    urls=[  
    ('/',views.index),  
    url(r'/index',views.index,name='index'),  
    (r'/login',views.login,{'subject':'python'}),  
    ('/raises',views.raises,{'key':121333}),  
    url(r'/upload_files',views.upload_files),  
    ]  
    #定义路由

(3)configs.py

    import os  

    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))  

    configs={  
        'debug':True,  
        'static_path':os.path.join(BASE_DIR,'app','static'),  
        'template_path':os.path.join(BASE_DIR,'app','templates'),  
        'compiled_template_cache':False,  
        'static_hash_cache':True,  
        "cookie_secret": "bZJc2sWbQLKos6GkHn/VB9oXwQt8S0R0kRvJ5/xJ89E=",  
        "xsrf_cookies": True,  

        "pycket":{  

                "engine": "redis",  
                "storage": {  
                    "host": "localhost",# 设置redis主机  
                    "port": 6379,# 设置链接端口  
                    "max_connections": 2**64# 设置最大连接数  
                },  
                "cookies": {  
                    "expires_days": 2 # 设置过期时间  
                }  

                }  

    }

(4)views.py

    from tornado.web import RequestHandler  
    import os  
    from sqlalchemy.orm import sessionmaker  
    from pycket.session import SessionMixin  

    from app.models import engine,User,Video  
    from app.config import BASE_DIR  

    dbsession=sessionmaker(engine)()  
    #初始化dbsesssion  

    class login(RequestHandler,SessionMixin):  
        def initialize(self,subject):  
            self.subject=subject  
        def get(self,*args,**kwargs):  
            self.xsrf_token  
            self.render('login.html')  
        def post(self,*args,**kwargs):  
            email=self.get_body_argument('email')  
            password=self.get_body_argument('password')  
            print(email,password)  
            res=dbsession.query(User).filter(User.email==email,User.password==password).first()  
            if res:  
                print(res.email,res.password)  
                self.session.set('user',email)  
                print(self.session.get('user'))  
                r_data={'code':1,'msg':'登陆成功'}  
            else:  
                r_data={'code':0,'msg':'邮箱或密码错误'}  
            self.write(r_data)  

    class index(RequestHandler):  
        def get(self,*args,**kwargs):  
            dic={'title':'电影列表'}  
            videos=dbsession.query(Video).filter().all()  
            self.render('index.html',videos=videos,dic=dic)  
    #定义视图

(5)models.py

    from sqlalchemy import create_engine  
    from sqlalchemy.ext.declarative import declarative_base  
    from sqlalchemy import Column,Integer,String  

    engine=create_engine('mysql+pymysql://root:@127.0.0.1:3306/test1')  
    Base=declarative_base()  

    class User(Base):  
        __tablename__='user'  
        id=Column(Integer,primary_key=True,autoincrement=True)  
        email=Column(String(64),primary_key=True)  
        password=Column(String(64))  

    class Video(Base):  
        __tablename__='video'  
        id=Column(Integer,primary_key=True,autoincrement=True)  
        title=Column(String(64))  
        click_num=Column(Integer)  

    Base.metadata.create_all(engine)

2.模板

1)变量渲染

    {{变量}}

2)流程控制

判断

    {%if valid==1%}  
    语句1  
    {%elif valid==2%}  
    语句2  
    {%else%}  
    语句3  
    {%end%}

循环

    {%for row in videos%}  
    {{row.title}}  
    {%end%}

3.视图函数

1)get参数接收

    self.get_query_argument()#接收单个参数  
    self.get_query_arguments()#接收多个参数

参数strip=True,表示去掉参数前后空格

2)post参数接收

    self.get_body_argument()#接收单个参数  
    self.get_body_arguments()#接收多个参数

3)cookie

(1)普通cookie
views函数中调用

    self.set_cookie()

(2)安全cookie
配置文件中新增键值对

    "cookie_secret": "bZJc2sWbQLKos6GkHn/VB9oXwQt8S0R0kRvJ5/xJ89E=",

views函数中调用

    self.set_secure_cookie()

4)xsrf

(1)配置文件中设置键值对

    "xsrf_cookies": True,

如此便开启xsrf,所有post请求都需要传入_xsrf随机字符串
(2)在views函数中设置cookie

    self.xsrf_token

5)session

(1)config.py中新增键值对

    configs={  
        "pycket":{  

                "engine": "redis",  
                "storage": {  
                    "host": "localhost",# 设置redis主机  
                    "port": 6379,# 设置链接端口  
                    "max_connections": 2**64# 设置最大连接数  
                },  
                "cookies": {  
                    "expires_days": 2 # 设置过期时间  
                }  

                }  
    }

(2)views函数中导入SessionMixin类,并在视图类中继承该类

    from pycket.session import SessionMixin

    class login(RequestHandler,SessionMixin):#继承SessionMixin类

        def initialize(self,subject):  
            self.subject=subject  
        def get(self,*args,**kwargs):  
            self.xsrf_token  
            self.render('login.html')  
        def post(self,*args,**kwargs):  
            email=self.get_body_argument('email')  
            password=self.get_body_argument('password')  
            print(email,password)  
            res=dbsession.query(User).filter(User.email==email,User.password==password).first()  
            if res:  
                print(res.email,res.password)  
                self.session.set('user',email)  
                print(self.session.get('user'))  
                r_data={'code':1,'msg':'登陆成功'}  
            else:  
                r_data={'code':0,'msg':'邮箱或密码错误'}  
            self.write(r_data)

6)错误处理

    class raises(RequestHandler):  
        def write_error(self,status_code,**kwargs):#自定义错误页面  
            if status_code==500:  
                self.write('服务器错误')  
            self.set_status(status_code)  
        def get(self,*args,**kwargs):  
            self.send_error(500)#抛出500错误

7)文件上传

    class upload_files(RequestHandler):  
        def get(self,*args,**kwargs):  
            self.render('upfiles.html')  
        def post(self,*args,**kwargs):  
            for inputname in self.request.files:  
                files=self.request.files[inputname]  
                for file in files:#遍历同一inputname的file  
                    filename=file['filename']  
                    new_filename=os.path.join(BASE_DIR,'app','uploadfiles',filename)  
                    with open(new_filename,'wb') as f:  
                        f.write(file['body'])#取出并写入file的body里的文件内容  
            self.write('ok')

4.url

1)两种定义方式

    urls=[  


        ('/raises',views.raises),

        url(r'/login',views.login,name='login'),#这种方式可定义url的name

    ]

2)字典参数

url中

    urls=[  
        ('/dics',views.dics,{'key':121333}),  
    ]

视图中

    class dics(RequestHandler):  
        def initialize(self,key):#将字典中的值初始化到views函数中  
            self.key=key  
        def get(self,*args,**kwargs):  
            self.write(self.key)#直接调用类属性

3)反向解析

定义name的路由,使用reverse_url()可反向解析其指向地址

5.模型

详见sqlalchemy

6.用户验证

1)config.py新增键值对"login_url":'/login',

    configs=[  
        "login_url":'/login',  
    ]

2)views.py中写一个BaseHander类,继承RequestHandler,SessionMixin,并重写get_current_user()

    from tornado.web import RequestHandler

    from pycket.session import SessionMixin

    class BaseHander(RequestHandler,SessionMixin):#需要继承SessionMixin,否则无法使用session  
        def get_current_user(self):  
            print(self.session.get('user'))  
            return self.session.get('user')

3)为目标视图函数新增装饰器@authenticated

    from tornado.web import authenticated  
    class index(BaseHander):  
        @authenticated  
        def get(self,*args,**kwargs):  
            dic={'title':'电影列表'}  
            videos=dbsession.query(Video).filter().all()  
            self.render('index.html',videos=videos,dic=dic)

7.异步

    from tornado.web import RequestHandler,gen  
    class implements(RequestHandler):  
        @gen.coroutine  
        def get(self,*args,**kwargs):  
            client=AsyncHTTPClient()  
            response= yield client.fetch("http://v.juhe.cn/toutiao/index")  
            self.on_response(response)  

        def on_response(self,response):  
            body=json.loads(response.body)  
            self.write(body)  
            self.finish()

还没有评论,来说两句吧