1102 tornado
5-6 RequestHandler的子类
RedirectHandler
# 1. RedirectHandler
# 301是永久重定向, 302是临时重定向,获取用户个人信息, http://www.baidu.com https
self.redirect方法和RedirectHandler方法区别是什么
self.redirect
可以定义业务逻辑,并根据逻辑选择是否跳转
RedirectHandler
在 url 进来的时候,就跳转
StaticFileHandler
配置静态文件的方式
方式一:
这样配置,方便多个项目静态文件的配置。
settings = { "static_path": "D:/Users/wenyule/Documents/PythonCode/tornado-forum/tornado_overview/chapter02/static", }
# 这样配置了,就要在创建APP实例的时候解包
if __name__ == "__main__": app = web.Application([ ("/", MainHandler), ("/2/", RedirectHandler, {"url": "/"}), ], debug=True, **settings) # 解包 app.listen(8888) tornado.ioloop.IOLoop.current().start()

更改静态文件访问的前缀
settings = { "static_path": "D:/Users/wenyule/Documents/PythonCode/tornado-forum/tornado_overview/chapter02/static", "static_url_prefix": "/static1/" }

方式二:
在url中配置
if __name__ == "__main__": app = web.Application([ ("/", MainHandler), ("/2/", RedirectHandler, {"url": "/"}), ("/static3/(.*)", StaticFileHandler, {"path": "D:/Users/wenyule/Documents/PythonCode/tornado-forum/tornado_overview/chapter02/static"}), ], debug=True, ) app.listen(8888) tornado.ioloop.IOLoop.current().start()

import time import tornado from tornado import web from tornado.web import StaticFileHandler, RedirectHandler # 1. RedirectHandler # 1. 301是永久重定向, 302是临时重定向,获取用户个人信息, http://www.baidu.com https # StaticFileHandler # web.URLSpec class MainHandler(web.RequestHandler): # 当客户端发起不同的http方法的时候, 只需要重载handler中的对应的方法即可 async def get(self, *args, **kwargs): time.sleep(5) self.write("hello world") class MainHandler2(web.RequestHandler): # 当客户端发起不同的http方法的时候, 只需要重载handler中的对应的方法即可 async def get(self, *args, **kwargs): self.write("hello world2") # 全局的静态文件配置目录 # # settings = { # "static_path": "D:/Users/wenyule/Documents/PythonCode/tornado-forum/tornado_overview/chapter02/static", # "static_url_prefix": "/static1/" # } urls = [ ("/", MainHandler), ("/2/", RedirectHandler, {"url": "/"}), ("/static3/(.*)", StaticFileHandler, {"path": "D:/Users/wenyule/Documents/PythonCode/tornado-forum/tornado_overview/chapter02/static"}), ] if __name__ == "__main__": app = web.Application(urls, debug=True, ) app.listen(8888) tornado.ioloop.IOLoop.current().start() # self.redirect方法和RedirectHandler方法区别是什么 # self.redirect
5-7 tornado的template
传统的加载模板文件的方式
方式一
import tornado from tornado.web import template class MainHandler(web.RequestHandler): # 当客户端发起不同的http方法的时候, 只需要重载handler中的对应的方法即可 async def get(self, *args, **kwargs): word = "hello bobboy" t = template.Template("<h1>{{ word }}</h2>") self.finish(t.generate(word=word))
方式二
import tornado from tornado.web import template class MainHandler(web.RequestHandler): async def get(self, *args, **kwargs): loader = template.Loader("hell.html") self.finish(loader.load("hello.html").generate(word=word))
高级正确的方式
settings = { "static_path":"C:/projects/tornado_overview/chapter02/static", "static_url_prefix":"/static2/", "template_path": "templates" # 模板配置的路径 }
web框架都会有模板功能
django和tornado对于模板的思路或者理念是完全不一样的
class MainHandler(web.RequestHandler): async def get(self, *args, **kwargs): word = "hello bobboy" self.render("index.html", word=word)
5-8 购物车列表页-template常用功能
template 模板语法
变量: {{ }}
标签: {% %}
块标签: {% block name %}
{% end %}
{% block custom_css %}
{% end %}
{% block custom_js %}
{% end %}
注意 {% end %}结尾
可以用作 base.html 页面留的钩子
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>网上超市</title> <link href="{{ static_url('css/public.css') }}" type="text/css" rel="stylesheet"> <link rel="stylesheet" type="text/css" href="{{ static_url('css/base.css') }}"> <link rel="stylesheet" type="text/css" href="{{ static_url('css/checkOut.css') }}"> {% block custom_css %} {% end %} </head> <body> <!--顶部快捷菜单--> <div class="shortcut_v2013 alink_v2013"> <div class="w"> <ul class="fl 1h"> <li class="fl"><i class="shortcut_s"></i></li> <li class="fl"> <div class="menu_hd"><a href="#">请登录</a></div> </li> <li class="fl"> <div class="menu_hd"><a href="#">免费注册</a></div> </li> </ul> <ul class="fr 1h"> <li class="fl"> <div class="menu_hd"><a href="#">我的订单</a></div> </li> <li class="fl"><i class="shortcut_s"></i></li> <li class="fl"> <div class="menu_hd"><a href="#">我的锡货</a></div> </li> <li class="fl"><i class="shortcut_s"></i></li> <li class="fl"> <div class="menu_hd"><a href="#">服务中心</a></div> </li> <li class="fl"><i class="shortcut_s"></i></li> <li class="fl"> <div class="menu_hd"><a href="#">商家入驻</a></div> </li> <li class="fl"><i class="shortcut_s"></i></li> <li class="fl"> <div class="menu"> <div class="menu_hd"><a href="#">网站导航</a><b><em></em></b></div> <div class="menu_bd"> <ul> <li><a href="#">网站导航</a></li> <li><a href="#">网站导航</a></li> </ul> </div> </div> </li> </ul> <span class="clr"></span> </div> </div> <div class="banner_red_top"></div> {% block body %} <h2>bobby</h2> {% end %} <div class="promise_box"> <div class="w"> <ul> <li><img src="{{ static_url('images/promise_img01.jpg') }}"><span>365天不打烊</span></li> <li><img src="{{ static_url('images/promise_img02.jpg') }}"><span>无理由退换货</span></li> <li><img src="{{ static_url('images/promise_img03.jpg') }}"><span>担保交易</span></li> <li><img src="{{ static_url('images/promise_img04.jpg') }}"><span>先行赔付</span></li> <li><img src="{{ static_url('images/promise_img05.jpg') }}"><span>支持定制</span></li> </ul> </div> </div> <div class="footer_v2013 bottom-about"> <div class="w"> <p class="foot_p1"> <a href="#">首页</a>|<a href="#">招聘英才</a>|<a href="#">广告合作</a>|<a href="#">联系我们</a>|<a href="#">关于我们</a> </p> <pre> 经营许可证:ICP备13041162号-1360网站安全检测平台 </pre> </div> </div> {% block custom_js %} {% end %} </body> </html>
{% extends 'base.html' %}
像编写Python程序一样,在HTML文件里面写逻辑
{% if total > 200%} <h1>钱不够</h1> {% else %} <h1> 买买 </h1> {% end %}
{% extends 'base.html' %} {% block body %} <div class="border_top_cart"> <div class="container"> <div class="checkout-box"> <form id="checkoutForm" action="#" method="post"> <div class="checkout-box-ft"> <div id="checkoutGoodsList" class="checkout-goods-box"> <div class="xm-box"> <div class="box-hd"> <h2 class="title">确认订单信息</h2> </div> <div class="box-bd"> <dl class="checkout-goods-list"> <dt class="clearfix"> <span class="col col-1">商品名称</span> <span class="col col-2">购买价格</span> <span class="col col-3">购买数量</span> <span class="col col-4">小计(元)</span> </dt> {% set total = 0 %} {% for order in orders %} <dd class="item clearfix"> <div class="item-row"> <div class="col col-1"> <div class="g-pic"> <img src="{{ order['image'] }}" srcset="{{ order['image'] }} 2x" width="40" height="40"> </div> <div class="g-info">{{ order['name'] }}</a></div> </div> {{ total = total+order['price']*order['nums'] }} {% from chapter02.utils import cal_total %} <div class="col col-2">{{ order['price'] }}元</div> <div class="col col-2">{{ order['nums'] }}</div> <div class="col col-2">{{ cal_total(order['price'],order['nums']) }}元</div> <div class="col col-2">{% raw order['detail'] %}</div> </div> </dd> {% end %} </dl> <div class="checkout-count clearfix"> <div class="checkout-price"> <ul> <li> 订单总额:<span>{{ total }}元</span> </li> <li> 运费:<span id="postageDesc">0元</span> </li> </ul> <p class="checkout-total">应付总额:<span><strong id="totalPrice">{{ total }}</strong>元</span></p> </div> <!-- --> </div> </div> </div> </div> </div> </form> </div> </div> </div> {% end %}
后端处理逻辑
# 1. 什么是模板 from tornado.web import StaticFileHandler, RedirectHandler # 1. RedirectHandler # 1. 301是永久重定向, 302是临时重定向,获取用户个人信息, http://www.baidu.com https # StaticFileHandler import time from tornado import web import tornado from tornado.web import template class MainHandler(web.RequestHandler): # 当客户端发起不同的http方法的时候, 只需要重载handler中的对应的方法即可 async def get(self, *args, **kwargs): # web框架都会有模板功能 # django和tornado对于模板的思路或者理念是完全不一样的 orders = [ { "name": "小米T恤 忍者米兔双截棍 军绿 XXL", "image": "http://i1.mifile.cn/a1/T11lLgB5YT1RXrhCrK!40x40.jpg", "price": 39, "nums": 3, "detail": "<a href='http://www.baidu.com'>查看详情</a>" }, { "name": "招财猫米兔 白色", "image": "http://i1.mifile.cn/a1/T14BLvBKJT1RXrhCrK!40x40.jpg", "price": 49, "nums": 2, "detail": "<a href='http://www.baidu.com'>查看详情</a>" }, { "name": "小米圆领纯色T恤 男款 红色 XXL", "image": "http://i1.mifile.cn/a1/T1rrDgB4DT1RXrhCrK!40x40.jpg", "price": 59, "nums": 1, "detail": "<a href='http://www.baidu.com'>查看详情</a>" } ] self.render("index.html", orders=orders) # word = "hello bobboy" # t = template.Template("<h1>{{ word }}</h2>") # self.finish(t.generate(word=word)) # # loader = template.Loader("hell.html") # self.finish(loader.load("hello.html").generate(word=word)) class MainHandler2(web.RequestHandler): # 当客户端发起不同的http方法的时候, 只需要重载handler中的对应的方法即可 async def get(self, *args, **kwargs): self.write("hello world2") settings = { "static_path": "D:/Users/wenyule/Documents/PythonCode/tornado-forum/tornado_overview/chapter02/static", "static_url_prefix": "/static2/", "template_path": "templates" } if __name__ == "__main__": app = web.Application([ ("/", MainHandler), ("/2/", RedirectHandler, {"url": "/"}), ("/static/(.*)", StaticFileHandler, {"path": "C:/projects/tornado_overview/chapter02/static"}) ], debug=True, **settings) app.listen(8888) tornado.ioloop.IOLoop.current().start() # self.redirect方法和RedirectHandler方法区别是什么 # self.redirect
5-9 template之页面继承和重载
5-10 tornado模板中UIModule
import tornado from tornado import web from tornado.web import StaticFileHandler class OrderModule(tornado.web.UIModule): def cal_total(self, price, nums): return price * nums def render(self, order, *args, **kwargs): """ 反回渲染 :param order: 传入的参数 :param args: :param kwargs: :return: """ return self.render_string("ui_modules/order-list.html", order=order, cal_total=self.cal_total) def embedded_css(self): return "body {background-color:green}" class MainHandler(web.RequestHandler): # 当客户端发起不同的http方法的时候, 只需要重载handler中的对应的方法即可 async def get(self, *args, **kwargs): # web框架都会有模板功能 # django和tornado对于模板的思路或者理念是完全不一样的 orders = [ { "name": "小米T恤 忍者米兔双截棍 军绿 XXL", "image": "http://i1.mifile.cn/a1/T11lLgB5YT1RXrhCrK!40x40.jpg", "price": 39, "nums": 3, "detail": "<a href='http://www.baidu.com'>查看详情</a>" }, { "name": "招财猫米兔 白色", "image": "http://i1.mifile.cn/a1/T14BLvBKJT1RXrhCrK!40x40.jpg", "price": 49, "nums": 2, "detail": "<a href='http://www.baidu.com'>查看详情</a>" }, { "name": "小米圆领纯色T恤 男款 红色 XXL", "image": "http://i1.mifile.cn/a1/T1rrDgB4DT1RXrhCrK!40x40.jpg", "price": 59, "nums": 1, "detail": "<a href='http://www.baidu.com'>查看详情</a>" } ] self.render("index2.html", orders=orders) settings = { "static_path": "D:/Users/wenyule/Documents/PythonCode/tornado-forum/tornado_overview/chapter02/static", "static_url_prefix": "/static2/", "template_path": "templates", "ui_modules": { "OrderModule": OrderModule } } if __name__ == "__main__": app = web.Application([ ("/", MainHandler), ("/static/(.*)", StaticFileHandler, {"path": "D:/Users/wenyule/Documents/PythonCode/tornado-forum/tornado_overview/chapter02/static"}) ], debug=True, **settings) app.listen(9999) tornado.ioloop.IOLoop.current().start()
settings = { "static_path": "C:/projects/tornado_overview/chapter02/static", "static_url_prefix": "/static2/", "template_path": "templates", "ui_modules": { "OrderModule": OrderModule # 配置文件,传到app里面去 } } if __name__ == "__main__": app = web.Application([ ("/", MainHandler), ("/2/", RedirectHandler, {"url": "/"}), ("/static/(.*)", StaticFileHandler, {"path": "C:/projects/tornado_overview/chapter02/static"}) ], debug=True, **settings) app.listen(8888) tornado.ioloop.IOLoop.current().start()
定义一个处理html模块的类
class OrderModule(tornado.web.UIModule): def cal_total(self, price, nums): # 自定义一个函数 return price * nums def render(self, order, *args, **kwargs): """ 反回渲染 :param order: 传入的参数 :param args: :param kwargs: :return: """ return self.render_string("ui_modules/order-list.html", order=order, cal_total=self.cal_total) def embedded_css(self): return "body {background-color:green}"
主要的部分
{% extends 'base.html' %} {% block body %} <div class="border_top_cart"> <div class="container"> <div class="checkout-box"> <form id="checkoutForm" action="#" method="post"> <div class="checkout-box-ft"> <div id="checkoutGoodsList" class="checkout-goods-box"> <div class="xm-box"> <div class="box-hd"> <h2 class="title">确认订单信息</h2> </div> <div class="box-bd"> <dl class="checkout-goods-list"> <dt class="clearfix"> <span class="col col-1">商品名称</span> <span class="col col-2">购买价格</span> <span class="col col-3">购买数量</span> <span class="col col-4">小计(元)</span> </dt> {% set total = 0 %} {% for order in orders %} {% module OrderModule(order) %} {% end %} </dl> <div class="checkout-count clearfix"> <div class="checkout-price"> <ul> <li> 订单总额:<span>{{ total }}元</span> </li> <li> 运费:<span id="postageDesc">0元</span> </li> </ul> <p class="checkout-total">应付总额:<span><strong id="totalPrice">{{ total }}</strong>元</span></p> </div> </div> </div> </div> </div> </div> </form> </div> </div> </div> {% end %}
模块化的部分
<dd class="item clearfix"> <div class="item-row"> <div class="col col-1"> <div class="g-pic"> <img src="{{ order['image'] }}" srcset="{{ order['image'] }} 2x" width="40" height="40"> </div> <div class="g-info">{{ order['name'] }}</a></div> </div> {% from chapter02.utils import cal_total %} <div class="col col-2">{{ order['price'] }}元</div> <div class="col col-2">{{ order['nums'] }}</div> <div class="col col-2">{{ cal_total(order['price'],order['nums']) }}元</div> <div class="col col-2">{% raw order['detail'] %}</div> </div> </dd>

5-11 tornado的settings
6-2 aiomysql完成数据的读写
异步 mysql 操作的模块
pip install aiomysql
Python 3.7 以后 async 已经是内置标识符 可以直接使用,不用再导入 import asyncio
import asyncio from tornado import ioloop from aiomysql import create_pool async def go(): async with create_pool(host='127.0.0.1', port=3306, user='root', password='123456', db='message', charset="utf8") as pool: async with pool.acquire() as conn: async with conn.cursor() as cur: await cur.execute("SELECT * from message") value = await cur.fetchone() print(value) if __name__ == "__main__": io_loop = ioloop.IOLoop.current() io_loop.run_sync(go)
6-3 数据的提交和修改
import tornado from tornado import web from aiomysql import create_pool class MainHandler(web.RequestHandler): def initialize(self, db): self.db = db async def get(self, *args, **kwargs): id = "" name = "" email = "" address = "" message = "" async with create_pool(host=self.db["host"], port=self.db["port"], user=self.db["user"], password=self.db["password"], db=self.db["name"], charset="utf8") as pool: async with pool.acquire() as conn: async with conn.cursor() as cur: await cur.execute("SELECT id, name, email, address, message from message") try: id, name, email, address, message = await cur.fetchone() except Exception as e: pass self.render("message.html", id=id, email=email, name=name, address=address, message=message) async def post(self, *args, **kwargs): id = self.get_body_argument("id", "") name = self.get_body_argument("name", "") email = self.get_body_argument("email", "") address = self.get_body_argument("address", "") message = self.get_body_argument("message", "") async with create_pool(host=self.db["host"], port=self.db["port"], user=self.db["user"], password=self.db["password"], db=self.db["name"], charset="utf8") as pool: async with pool.acquire() as conn: async with conn.cursor() as cur: if not id: await cur.execute( "INSERT INTO message(name, email, address, message) VALUES('{}','{}','{}','{}')".format( name, email, address, message)) await cur.execute("SELECT id from message where name='{}'".format(name)) try: id = await cur.fetchone() except Exception as e: pass else: await cur.execute( "update message set name='{}', email='{}', address='{}', message='{}'".format(name, email, address, message)) await conn.commit() self.render("message.html", id=id, email=email, name=name, address=address, message=message) settings = { "static_path": "D:/Users/wenyule/Documents/PythonCode/tornado-forum/tornado_overview/chapter03/static", "static_url_prefix": "/static/", "template_path": "templates", "db": { "host": "127.0.0.1", "user": "root", "password": "123456", "name": "message", "port": 3306 } } if __name__ == "__main__": app = web.Application([ ("/", MainHandler, {"db": settings["db"]}), ], debug=True, **settings) app.listen(8888) tornado.ioloop.IOLoop.current().start()
7-3 model的数据保存
import peewee_async # 异步orm
使用异步的数据库连接以后就不能再以同步的方式去编程
from datetime import datetime from peewee import * from peewee import Model import peewee_async # 异步orm db = MySQLDatabase('message', host="127.0.0.1", port=3306, user="root", password="123456") # 异步的数据库连接 database = peewee_async.MySQLDatabase( 'message', host="127.0.0.1", port=3306, user="root", password="123456" ) objects = peewee_async.Manager(database) # No need for sync anymore! database.set_allow_sync(False) # 设置非同步 class BaseModel(Model): add_time = DateTimeField(default=datetime.now, verbose_name="添加时间") class Meta: # database = database #异步的数据库连接 database = db class Supplier(BaseModel): name = CharField(max_length=100, verbose_name="名称", index=True) address = CharField(max_length=100, verbose_name="联系地址") phone = CharField(max_length=11, verbose_name="联系方式") class Meta: database = db table_name = "supplier" class Goods(BaseModel): supplier = ForeignKeyField(Supplier, verbose_name="商家", backref="goods") name = CharField(max_length=100, verbose_name="商品名称", index=True) click_num = IntegerField(default=0, verbose_name="点击数") goods_num = IntegerField(default=0, verbose_name="库存数") price = FloatField(default=0.0, verbose_name="价格") brief = TextField(verbose_name="商品简介") class Meta: table_name = "goods" def init_table(): db.create_tables([Goods, Supplier]) if __name__ == "__main__": init_table()
本文来自博客园,作者:元贞,转载请注明原文链接:https://www.cnblogs.com/yuleicoder/articles/13916315.html
浙公网安备 33010602011771号