文章详情页 您现在的位置是:网站首页>文章详情
关于tornado框架
Jeyrce.Lu 发表于:2019年6月21日 23:20 分类:【Python】 2964次阅读
之前的笔记
这里是以前自己学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篇
- 加入本站:2046天
作者其他文章
站长推荐
友情链接
站点信息
- 运行天数:2047天
- 累计访问:164169人次
- 今日访问:0人次
- 原创文章:69篇
- 转载文章:4篇
- 微信公众号:第一时间获取更新信息