文章详情页 您现在的位置是:网站首页>文章详情
关于tornado框架
Jeyrce.Lu
发表于:2019年6月21日 23:20
分类:【Python】
3554次阅读
之前的笔记
这里是以前自己学tornado框架做的笔记,我放在有道云上,周末我又看了一下。 tornado的学习笔记
以下关键点笔记记录于2019-06-26日
Django是python语言中最为全面、典型的web框架,我对django较熟悉,之后我自己又看了flask, bottle, 现在又看了tornado, 我不得不说,django确实是最值得学习的!
tornado快速上手关键点
(一)例子: app加载路由、配置,传给httpserver、开启ellpo事件循环
-----handlers.py
from tornado.web import RequestHandler
import db
import ex
from index import utils
from db import get_session, open_session
class BaseHandler(RequestHandler):
"""
一些公共的操作
"""
session = None
def prepare(self):
setattr(self, 'session', db.open_session())
def on_finish(self):
if self.session:
self.session.close()
class IndexHandler(BaseHandler):
def get(self, *args, **kwargs):
area = db.Area(name=self.get_argument('name', utils.random_string()))
self.session.add(area)
self.session.commit()
self.render('index.html', **{'web': area})
class AccountAreaHandler(BaseHandler):
def get(self, *args, **kwargs):
accounts = self.session.query(db.Account).all()
self.write(json.dumps([{'area': a.area.name, 'name': a.username} for a in accounts]))
class ReverUrlTestHandler(RequestHandler):
def get(self, *args, **kwargs):
self.render('test_url_reverse.html')------ urls.py
from tornado.web import URLSpec as U
# fixme: from tornado.web import url 这个url就是URLSpec
# 实际上我怎么觉得这个URLSpec就是来搞笑的,直接传元祖也没什么问题
from index import handlers
url_list = (
U(r'/index.html', handlers.IndexHandler),
U(r'/account', handlers.AccountAreaHandler, {}, '222'),
('/xxx', handlers.ReverUrlTestHandler, {}, 'xxx'),
)-----run.py
from tornado import web from tornado.ioloop import IOLoop from index.urls import url_list from config import SETTINGS if __name__ == '__main__': app = web.Application(handlers=url_list, debug=True, autoreload=True, **SETTINGS) app.listen(8000) IOLoop.current().start()
(二)tornado响应: 继承tornado.web.RequestHandler类,实现get...delete请求方式对应的function即可
RequestHandler直接父类:object,他是tornado提供的一种基础handler
实现的方法及作用:
initialize: 在__init__方法最后进行调用,是__init__方法的扩展,用于初始化handler实例时扩展操作,父类pass
head、get、post、options、put、patch、delete七种对应请求方式的方法,目前只是抽象出来,父类raise 405,意味着继承这个类的必须自己实现对应方法覆盖他
prepare、on_finish,这两个方法分别在执行请求视图(get、header、options等)之前和之后调用,父类pass
set_default_headers,设置默认响应头,父类pass
get_arguments、get_query_arguments,获取请求参数
cookies、get_cookie、set_cookie、clear_cookie、clear_all_cookies、set_secure_cookie、get_secure_cookie,和cookie相关的操作
rediect,重定向,通过参数决定是永久还是临时
write,用于返回响应,相应数据可以是bytes, unicode_type, dict三种类型
render、render_string、get_template_namespace、create_template_loader,和模板渲染有关的函数
finish,结束响应,清空buff,调用do_finish等
get_current_user,父类pass,自己覆盖用以进行authenticate,覆盖后可self.current_user取用
_execute,此方法是响应请求的关键方法,他从handler实例中寻找对应于请求的handler,以及default_handler,没有则raise405,否则执行对应函数(此方法使用gen.croutine装饰,异步执行)
if self.request.method not in self.SUPPORTED_METHODS: raise HTTPError(405) ... method = getattr(self, self.request.method.lower()) result = method(*self.path_args, **self.path_kwargs)
class BaseHandler(RequestHandler): """ 一些公共的操作 """ session = None def prepare(self): setattr(self, 'session', db.open_session()) def on_finish(self): if self.session: self.session.close()
(三)tornado路由:给app传入一个[(regex, handler_cls, kw_dict, name)]这样的路由列表即可
(1) 创建app实例时传入
url_list = (
U(r'/index.html', handlers.IndexHandler),
U(r'/account', handlers.AccountAreaHandler, {}, '222'),
('/xxx', handlers.ReverUrlTestHandler, {}, 'xxx'),
)
if __name__ == '__main__':
app = web.Application(handlers=url_list, debug=True, autoreload=True, **SETTINGS)
app.listen(8000)
IOLoop.current().start()(2)创建app实例之后添加(也可用于子域名)
url_list = (
U(r'/index.html', handlers.IndexHandler),
U(r'/account', handlers.AccountAreaHandler, {}, '222'),
('/xxx', handlers.ReverUrlTestHandler, {}, 'xxx'),
)
url_list2 = [
.....如上
]
if __name__ == '__main__':
app = web.Application(handlers=url_list, debug=True, autoreload=True, **SETTINGS)
app.add_handlers('.*$', url_list2)
app.listen(8000)
IOLoop.current().start()(四)tornado操作数据库:他自己的torndb功能太简单了,我们使用sqlalchemy来进行orm操作
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from multiprocessing import cpu_count
from contextlib import contextmanager
from sqlalchemy import create_engine
from sqlalchemy import Column, Integer, String, DateTime, Boolean, func, Index, ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy.schema import MetaData
mysql = {
'username': 'root',
'password': 'ljX.07',
'host': '127.0.0.1',
'port': 3306,
'database_name': 'idea'
}
engine_str = 'mysql+mysqldb://{username}:{password}@{host}:{port}/{database_name}?charset=utf8'.format(**mysql)
engine = create_engine(
engine_str,
encoding='utf8',
echo=False,
pool_size=cpu_count() * 2,
max_overflow=cpu_count(),
pool_recycle=600,
pool_timeout=600,
)
meta_data = MetaData(bind=engine)
@contextmanager
def get_session():
Session = sessionmaker(bind=engine, autocommit=False, autoflush=False, expire_on_commit=False)
session = Session()
yield session
session.close()
def open_session():
Session = sessionmaker(bind=engine, autocommit=False, autoflush=False, expire_on_commit=False)
session = Session()
return session
class Base(object):
__table_args__ = {
"mysql_engine": "InnoDB",
"mysql_charset": "utf8"
}
BaseModel = declarative_base(bind=engine, name='BaseModel', metadata=meta_data, cls=Base)
class Area(BaseModel):
"""
区域表
"""
__tablename__ = 'area'
# 自增id
id = Column(name='id', type_=Integer, autoincrement=True, primary_key=True, comment='id')
# 字符串类型
name = Column(name='name', type_=String(20), nullable=False, unique=True, comment=u'名字')
# 时间自动更新
add = Column(name='add', type_=DateTime, server_default=func.now(), comment=u'添加时间')
mod = Column(name='mod', type_=DateTime, server_onupdate=func.now(), comment=u'最近更新')
# 布尔类型
is_active = Column(name='is_active', type_=Boolean, default=True, comment=u'是否可用')
def __repr__(self):
return self.name
class Account(BaseModel):
"""
账户表
"""
__tablename__ = 'account'
id = Column(name='id', type_=String(32), primary_key=True, comment='uuid')
username = Column(name='username', type_=String(20), unique=True, comment=u'用户名')
area_id = Column('area_id', ForeignKey(column='area.id', ondelete='CASCADE'))
area = relationship('Area', backref='Account_area_id')
add = Column(name='add', type_=DateTime, server_default=func.now(), comment=u'创建时间')
mod = Column(name='mod', type_=DateTime, server_onupdate=func.now(), comment=u'上次变更')
is_active = Column(name='is_active', type_=Boolean, default=True, comment=u'是否可用')
def __repr__(self):
return self.username
if __name__ == '__main__':
BaseModel.metadata.create_all(checkfirst=True)
这里的操作有几个关键点
创建engine,创建session
declarative_base创建一个基类,之后我们所有的表都继承这个基类,之后基类就可以一键生成表,描述表的关系
使用orm时,我们创建一个session, 然后session.add, session.query等等操作带入model类即可
class IndexHandler(BaseHandler):
def get(self, *args, **kwargs):
area = db.Area(name=self.get_argument('name', utils.random_string()))
self.session.add(area)
self.session.commit()
self.render('index.html', **{'web': area})(五)tornado后端渲染
tornado如众多web框架一样支持模板语言后端渲染,他的RequestHandler提供了render和render_string两个function来执行这一操作,模板语法类似于jinja2, django的DTL等
handler这么写
class TemplateHandler(RequestHandler):
"""
模板渲染示例
"""
def get(self, *args, **kwargs):
ctx = {
'email': 'jeeyshe@gmail.com',
'site': 'https://www.lujianxin.com',
'lines': ['江山不换韩云汐', '青城山下白素贞', '《落花成泥》', '《叹云兮》']
}
self.render('info.html', **ctx)
html模板语言这么写
<span>联系方式:</span>: {{ email }}<br>
<span>网站地址:</span>: <a href="{{ site }}" target="_blank">{{ site }}</a><br>
{% for line in lines %}
<p>{{ line }}</p>
{% end for %}
渲染后的效果
最后说一句:web框架大同小异,django确实是python语言中最全面、典型的web框架
版权声明 本文属于本站 原创作品,文章版权归本站及作者所有,请尊重作者的创作成果,转载、引用自觉附上本文永久地址: http://blog.lujianxin.com/x/art/7ji2jdhiscqr
猜你喜欢
文章评论区
作者名片
- 作者昵称:Jeyrce.Lu
- 原创文章:61篇
- 转载文章:3篇
- 加入本站:2387天
作者其他文章
站长推荐
友情链接
站点信息
- 运行天数:2388天
- 累计访问:164169人次
- 今日访问:0人次
- 原创文章:69篇
- 转载文章:4篇
- 微信公众号:第一时间获取更新信息
