tornado
请求与响应
请求
-
接收get传递参数
获取请求URL中的参数: self.get_argument('name')/self.get_arguments('name')
self.get_query_argument('name')/ self.get_query_arguments('name')
-
接收post传递参数
获取请求体body传递的参数: self.get_argument('name')/self.get_arguments('name')
self.get_body_argument('name')/ self.get_body_arguments('name')
响应
Tornado应用
定义make_app函数
获取(返回)tornado.web.Application对象
对象的参数handlers=[(访问路由,执行方法),]
监听端口:Application对象.listen(端口)
执行方法类,需继承tornado.web.RequestHandler
如果处理get请求,则定义def get(self)方法
如果处理post请求,则定义def post(self)方法
启动
获取应用: app = make_app()
tornado.ioloop.IOLoop.current().start()
命令行
定义默认的监听端口:
define('port', default=8080, type=int)
解析命令行中参数:parse_command_line()
获取命令行中的port参数:options.port
启动命令:python xxx.py --port=端口值
继承了RequestHandler的类
关于get等请求方法的应用
def get(self, month, year, day):
self.write('%s年%s月%s日' % (year, month, day))
def post(self, month, year, day):
self.write('post:只负责新增数据')
def delete(self, month, year, day):
self.write('delete:只负责删除')
def patch(self, month, year, day):
self.write('patch:修改部分属性')
def put(self, month, year, day):
self.write('put:修改全部属性')
### 跳转:self.redirect('/路由/')
### 一般在initialize方法中通过pymysql连接数据库
self.connect_obj = pymysql.connect( host='127.0.0.1', user='root', password='zhuming', database='flask9', port=3306, charset='utf8', autocommit=True ) # cursor参数pymysql.cursors.DictCursor定义取出的数据格式 self.cursor = self.connect_obj.cursor(pymysql.cursors.DictCursor)
### def initialize(self):
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" contenteditable="true" cid="n54" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">self.write('访问路由的时候开始时自动调用')</pre>
### def prepare(self):
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" contenteditable="true" cid="n56" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">self.write('访问路由的时候在initialize之后调用')</pre>
### 其他的get, post, put, patch, delete等方法写在中间
### def on_finish(self):
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" contenteditable="true" cid="n59" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">self.write('访问路由的时候结束时自动调用')</pre>
cookie
添加cookie:self.set_cookie('name', 'value', expires/expires_days)
其中expires=日期,值可以通过datetime.now() + timedelta(days=值) 设置
其中expires_days=正整数,代表几天后消失
删除cookie,只能删除值,不能删除键
self.clear_cookie('name') self.clear_all_cookies()
路由定义
第一种
定义:tornado.web.Application(handlers=[(r'/days/(\d+)/(\d+)/', DaysHandler), ])
def get(self, month, day)
注意:路由中的第一个参数,被函数中定义的month接收,第二个参数被函数中定义的day接收
第二种
定义:tornado.web.Application(handlers=[(r'/days/(?P<name>\d+)/(?P<name2>\d2)', DaysHandler), ])
def get(self, name2, name)
注意:路由中的第一个参数取名为name,第二个参数取名为name2
HTTP行为方法
GET:只用于获取数据
POST:只用于创建数据
PUT:修改某个对象的全部属性
PATCH:修改某个对象的部分属性
DELETE:删除数据
切入点函数
def initialize(self): 实例化初始内容,在调用行为方法之前将自动调用
def prepare(self): 在调用行为方法之前将自动调用
def on_finish(self): 在调用行为方法之后将自动调用
模板
模板文件路径定义:Application(handlers=[], template_path='指定templates文件夹的路径')
获取templates路径:os.path.join(os.path.dirname(os.path.abspath(file)), 'templates')
父模板
- 挖坑:{% block name %} {% end %}
子模板
- 继承:{% extends '父模板名称' %}
模板语法
-
标签:{% 标签名 %} {% end %}
if标签:{% if 条件 %} {% end %}、{% if 条件 %} {% elif 条件 %} {% else %} {% end %}
for标签:{% for 变量 in [] %} {% end %}
set标签:{% set 变量=值 %}
while标签:{% while 条件 %} {% end %}
try标签:{% try %} {% except %} {% finally %} {% end %}
变量:{{ 变量名 }}
注解:{# 注解内容 #}
静态文件配置与使用
配置:tornado.web.Application(handlers=[], template_path='', static_path='')
static_path=os.path.join(os.path.dirname(os.path.abspath(file)), 'static')
导入静态文件: href='/static/css/xxx.css'、 href={{ static_url('css/xxx.css') }}
模型
1、模型定义:必须继承于Base = declarative_base(bind=engine)
2、数据库连接配置:mysql+pymysql://root:zhuming@127.0.0.1:3306/database
3、创建连接、引擎:create_engine(连接地址)
4、创建会话对象:
DbSession = session_maker(bind=engine) session = DbSession()
增
session.add(对象) session.commit()
session.add_all(对象列表) session,commit()
删
session.delete(对象) session.commit()
filter(条件).delete() session.commit()
查
session.query(模型).filter(条件).all() session.query(模型).filter(条件).first()
filter(模型名.字段 == 值)
filter_by(字段 = 值)
改
同增的操作
filter(条件).update({'key': 'value', 'key2': 'value2'})
同步/异步
同步请求
class IndexHandler(tornado.web.RequestHandler):
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" contenteditable="true" cid="n169" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">def get(self):
# 路由中传递的参数,/index/?q=python
q = self.get_argument('q')
# 向地址发送请求:https://cn.bing.com/search?q=
client = tornado.httpclient.HTTPClient()
response = client.fetch('https://cn.bing.com/search?q=%s' % q)
print(response)
self.write('同步测试')</pre>
异步请求
class IndexHandler(tornado.web.RequestHandler):
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" contenteditable="true" cid="n172" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">def get(self):
# 路由中传递的参数,/index/?q=python
q = self.get_argument('q')
# 向地址发送请求:https://cn.bing.com/search?q=
client = tornado.httpclient.HTTPClient()
response = client.fetch('https://cn.bing.com/search?q=%s' % q)
print(response)
self.write('同步测试')</pre>
### 异步请求简化
class IndexHandler(tornado.web.RequestHandler): @tornado.web.asynchronous @tornado.web.gen.coroutine def get(self): q = self.get_argument('q') client = tornado.httpclient.AsyncHTTPClient() response = yield client.fetch('[https://cn.bing.com/search?q=%s](https://cn.bing.com/search?q=%25s)' % q) print(response) self.write('异步测试')
客户端与服务器保持连接
class ChatHandler(tornado.websocket.WebSocketHandler): # 用于存放连接的对象 user_online = []
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" contenteditable="true" cid="n177" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">def open(self, *args, **kwargs):
# 当进入chat.html页面时,会主动触发该函数
self.user_online.append(self)
for user in self.user_online:
# 给每个在线用户推送这条消息
# username = self.get_cookie('username')
username = self.get_secure_cookie('username').decode('utf-8')
user.write_message('系统提示:【%s】已进入聊天室' % username)
def on_message(self, message):
# 接收前端传的数据
username = self.get_secure_cookie('username').decode('utf-8')
for user in self.user_online:
# 给每个在线用户推送这条消息
user.write_message('%s: %s' % (username, message))
def on_close(self):
# 移除连接对象
self.user_online.remove(self)
for user in self.user_online:
# 给每个在线用户推送这条消息
username = self.get_secure_cookie('username').decode('utf-8')
user.write_message('系统提示:【%s】已退出聊天室' % username)</pre>
后端方法
业务类继承tornado.websocket.WebSocketHandler
def open(self, *args, **kwargs): 跳转到该路由时自动触发该函数
向前端发送消息 self.write_message('内容')
-
def on_message(self, message):
message就是前端传过来的数据
-
def on_close(self):
移除连接对象的时候自动调用
前端方法
<!--建立连接--> var websocket = new WebSocket('ws://127.0.0.1:80/chat/')
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" contenteditable="true" cid="n194" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> <!--获取后端返回的数据-->
websocket.onmessage = function(e){
console.log(e.data)
$('#chat').append(e.data)
$('#chat').append('<br>')
}
$('#btn').click(function(){
<!--向后端发送数据-->
var content = $('#content').val()
websocket.send(content)
})</pre>
* 在js中编写,首先建立一个连接 var websocket = new WebSocket('ws://127.0.0.1:80/路由名/')
* 获取后端返回的数据 websocket.onmessage = function(e){ console.log(e.data) }
* 向后端发送数据 websocket.send(content)