Tornado总结
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()还没有评论,来说两句吧
