整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

Python Web 框架之 Tornado

Python Web 框架之 Tornado

.Tornado

  • Tornado:python编写的web服务器兼web应用框架

1.1.Tornado的优势

  • 轻量级web框架
  • 异步非阻塞IO处理方式
  • 出色的抗负载能力
  • 优异的处理性能,不依赖多进程/多线程,一定程度上解决C10K问题
  • WSGI全栈替代产品,推荐同时使用其web框架和HTTP服务器

1.2.Tornado VS Django

  • Django:重量级web框架,功能大而全,注重高效开发
  • 内置管理后台
  • 内置封装完善的ORM操作
  • session功能
  • 后台管理
  • 缺陷:高耦合
  • Tornado:轻量级web框架,功能少而精,注重性能优越
  • HTTP服务器
  • 异步编程
  • WebSocket
  • 缺陷:入门门槛较高

2.安装

输入命令:

pip install tornado

备注:

Tornado应该运行在类Unix平台,为了达到最佳的性能和扩展性,仅推荐Linux和BSD(充分利用Linux的epoll工具和BSD的kqueue达到高性能处理的目的)

3.使用

3.1.Tornado入门程序 - (一)

#-*- coding:utf-8 -*-import tornado.webimport tornado.ioloop#定义处理类型class IndexHandler(tornado.web.RequestHandler):
 #添加一个处理get请求方式的方法
 def get(self):
 #向响应中,添加数据
 self.write('好看的皮囊千篇一律,有趣的灵魂万里挑一。')if __name__=='__main__': #创建一个应用对象
 app=tornado.web.Application([(r'/',IndexHandler)]) #绑定一个监听端口
 app.listen(8888) #启动web程序,开始监听端口的连接
 tornado.ioloop.IOLoop.current().start()

1 .在pycharm中直接运行代码

2 .如果是在ubuntu,在命令窗口输入

python 文件名.py

使用浏览器访问

4.Tornado 代码解析

4.1.入门程序代码解析

  • tornado.web:tornado的基础web框架
  • RequestHandler:封装对请求处理的所有信息和处理方法
  • get/post/..:封装对应的请求方式
  • write():封装响应信息,写响应信息的一个方法
  • tornado.ioloop:核心io循环模块,封装linux的epoll和BSD的kqueue, tornado高性能处理的核心。
  • current()返回当前线程的IOLoop实例对象
  • start()启动IOLoop实力对象的IO循环,开启监听

4.2.httpserver底层处理

  • httpserver监听端口
tornado.httpserver.HTTPServer(app)httpserver.listen(port)
  • httpserver实现多进程操作
tornado.httpserver.HTTPServer(app)
httpserver.bind(port)
httpserver.start(0/None/<0/num)
# -*- coding:utf-8 -*-from tornado.web import Application,RequestHandlerfrom tornado.ioloop import IOLoopfrom tornado.httpserver import HTTPServerclass IndexHandler(RequestHandler):
 def get(self):
 self.write('给自己一点时间,理清所有的荒唐与期望。')if __name__=='__main__':
 app=Application([(r'/',IndexHandler)])
 http_server=HTTPServer(app) #最原始的方式
 http_server.bind(8888)
 http_server.start(1) #启动Ioloop轮循监听
 IOLoop.current().start()

同时打开两个窗口测试发现实现了多进程

4.3.options配置

  • 全局配置
tornado.options.define(
 name, default, type, multiple, help)
  • 命令行参数转换
tornado.options.parse_command_line()
#-*- coding:utf-8 -*-from tornado.web import RequestHandler,Applicationfrom tornado.ioloop import IOLoopfrom tornado.httpserver import HTTPServerimport tornado.options#定义变量tornado.options.define('port',default=8000,type=int,help="this is the port >for application")class IndexHandler(RequestHandler):
 def get(self):
 self.write('我们既然改变不了规则,那就做到最好')if __name__=='__main__':
 app=Application([(r'/',IndexHandler)])
 tornado.options.parse_command_line()
 http_server=HTTPServer(app)
 http_server.bind(tornado.options.options.port)
 http_server.start(1) #启动IOLoop轮循监听
 IOLoop.current().start()

通过命令窗口输入port来访问

通过使用我们命令窗口设定的port进行访问

  • 配置文件
#即在当前py文件目录创建config文件,并在py代码中加入以下代码,tornado.options.parse_config_file("./config")
  • 配置模块:跟配置文件类似

4.4.application配置

  • 程序调试之debug配置
#自动重启+取消缓存模板+取消缓存静态文件+提供追踪信息tornado.web.Application([(..)], debug=True)
注:开发之初可以设置debug=True方便调试,开发完毕改为False.
  • 路由信息初始化参数配置
tonado.web.Application([(r””, Handler, {k:v})])def initialize(self, k)
  • 路由名称设置及反解析
#名称设置tornado.web.Application([
 url(r””, handler, {k,v}, name=“”)
])#反解析操作reverse_url(name)

实例

# -*- coding:utf-8 -*-from tornado.web import Application, RequestHandler, urlfrom tornado.ioloop import IOLoopfrom tornado.httpserver import HTTPServerclass IndexHandler(RequestHandler):
 def get(self):
 self.write("<a href='"+self.reverse_url("login")+"'>用户登录</a>")class RegistHandler(RequestHandler):
 def initialize(self, title):
 self.title=title def get(self):
 self.write("注册业务处理:" + str(self.title))class LoginHandler(RequestHandler):
 def get(self):
 self.write("用户登录页面展示") def post(self):
 self.write("用户登录功能处理")if __name__=="__main__":
 app=Application(
 [
 (r"/", IndexHandler),
 (r"/regist", RegistHandler, {"title": "会员注册"}),
 url(r"/login", LoginHandler, name="login"),
 ]
 )
 http_server=HTTPServer(app)
 http_server.listen(8000)
 IOLoop.current().start()

4.5.参数传递

  • get方式传递参数
get_query_arguments(name,default=_ARG_DEFAULT,strip=True)
get_query_argument(name ,strip=True)
  • post方式传递参数
get_body_arguments(name, default=_ARG_DEFAULT,strip=True)
get_body_argument(name ,strip=True)

实例

# -*- coding:utf-8 -*-from tornado.web import Application, RequestHandlerfrom tornado.ioloop import IOLoopfrom tornado.httpserver import HTTPServerclass IndexHandler(RequestHandler):
 def get(self):
 # 获取get方式传递的参数
 username=self.get_query_argument("username")
 usernames=self.get_query_arguments("username") print (username) print (usernames) def post(self):
 # 获取post方式传递的参数
 username=self.get_body_argument("username")
 usernames=self.get_body_arguments("username") print (username) print (usernames)if __name__=="__main__":
 app=Application([(r"/",IndexHandler)])
 app.listen(8000)
 IOLoop.current().start()#网页运行时需要传入参数#192.168.11.79:8000/?username=123
  • 混合方式
get_arguments(..)/get_argument(..)

实例

# -*- coding:utf-8 -*-from tornado.web import Application, RequestHandlerfrom tornado.ioloop import IOLoopclass IndexHandler(RequestHandler):
 def get(self):
 # 获取get方式的参数
 user=self.get_argument("user")
 print("get方式获取参数:" + str(user)) def post(self):
 # 获取post方式的参数
 user=self.get_argument("user")
 print("post方式获取参数:" + user.encode("utf-8"))if __name__=="__main__":
 app=Application([(r"/", IndexHandler)])
 app.listen(8000)
 IOLoop.current().start()
  • 其他参数
通过request获取参数数据
method/host/uri/path/query/version/headers/body/remote_ip/files

实例

  • request/json
# -*- coding:utf-8 -*-from tornado.web import Application, RequestHandlerfrom tornado.ioloop import IOLoopclass IndexHandler(RequestHandler):
 def get(self):
 print self.request
 json_str={"username": "admin", "password": "123123"}
 self.write(json.dumps(json_str))if __name__=="__main__":
 app=Application([(r"/", IndexHandler)])
 app.listen(8000)
 IOLoop.current().start()
  • header

.add_header() .set_header().set_default_headers()设置响应HTTP头, 前两者的不同点在于多次设置同一个项时,.add_header()会叠加参数, 而.set_header()则以最后一次为准..set_default_headers()比较特殊, 是一个空方法, 可根据需要重写, 作用是在每次请求初始化RequestHandler时设置默认headers

.

  • .clear_header() .clear().clear_header()

清除指定的headers, 而.clear()清除.set_default_headers()以外所有的headers设置.

# add_headerself.add_header('Foo', 'one')self.add_header('Foo', 'two')# set_headerself.set_header('Bar', 'one')self.set_header('Bar', 'two')# HTTP头的设置结果# Foo → one, two# Bar → two

# -*- coding:utf-8 -*-from tornado.web import Application, RequestHandlerfrom tornado.ioloop import IOLoopclass IndexHandler(RequestHandler):
 def set_default_headers(self):
 # 第二种响应头设置方式
 print("---------> 响应头set_default_headers()执行")
 self.set_header("Content-type", "application/json; charset=utf-8")
 self.set_header("qiku", "奇酷信息") def get(self):
 # 第一种操作响应头的方式:
 # self.set_header("Content-type", "application/json")
 print("---------->get方法执行")
 self.write("{'name':'jerry'}")
 self.set_header("qiku", "qikuedu.com")if __name__=="__main__":
 app=Application([(r"/", IndexHandler)])
 app.listen(8000)
 IOLoop.current().start()
  • writerror

.send_error()用于发送HTTP错误页(状态码). 该操作会调用.clear().set_status().write_error()用于清除headers, 设置状态码, 发送错误页. 重写.write_error()可以自定义错误页.

  • # -*- coding:utf-8 -*-from tornado.web import Application, RequestHandlerfrom tornado.ioloop import IOLoopclass IndexHandler(RequestHandler):
 def get(self):
 self.write("hello qikuedu.com")
 self.send_error(404, msg="页面丢失", info="家里服务器搞对象去了") def write_error(self, status_code, **kwargs):
 self.write("<h1>出错啦,工程师MM正在赶来的途中...</h1>")
 self.write("<p>错误信息:%s</p>" % kwargs["msg"])
 self.write("<p>错误描述:%s</p>" % kwargs["info"])if __name__=="__main__":
 app=Application([(r"/", IndexHandler)])
 app.listen(8000)
 IOLoop.current().start()

数据流

  • .write()将数据写入输出缓冲区. 如果直接传入

dict, 那Tornado会自动将其识别为json, 并把Content-Type设置为application/json, 如果你不想要这个Content-Type, 那么在.write()之后, 调用.set_header()重新设置就好了. 需要注意的是, 如果直接传入的是list, 考虑到安全问题(json数组会被认为是一段可执行的JavaScript脚本, 且<script src="*/secret.json">可以绕过跨站限制),list将不会被转换成json.

  • .flush()
  • 将输出缓冲区的数据写入socket. 如果设置了callback, 会在完成数据写入后回调. 需要注意的是, 同一时间只能有一个"等待"的flush callback, 如果"上一次"的flush callback还没执行, 又来了新的flush, 那么"上一次"的flush callback会被忽略掉.
  • .finish()
  • 完成响应, 结束本次请求. 通常情况下, 请求会在return时自动调用.finish(), 只有在使用了异步装饰器@asynchronous或其他将._auto_finish设置为False的操作, 才需要手动调用.finish()

.

  • cookie
# -*- coding:utf-8 -*-
from tornado.web import Application, RequestHandlerfrom tornado.ioloop 
import IOLoop
class IndexHandler(RequestHandler):
 def get(self):
 self.write("hello qikuedu.com")
 self.set_cookie("loginuser", "admin老王") print self.get_cookie("loginuser") print self.cookiesif __name__=="__main__":
 app=Application([(r"/", IndexHandler)])
 app.listen(8000)
 IOLoop.current().start()

页面

  • .render()
  • 返回渲染完成的html. 调用后不能再进行输出操作.
  • .redirect()
  • 重定向, 可以指定3xx重定向状态码. 调用后不能再进行输出操作.
# 临时重定向 301self.redirect('/foo')# 永久重定向 302self.redirect('/foo', permanent=True)# 指定状态码, 会忽略参数 permanentself.redirect('/foo', status=304)
  • redirect

蚂蚁开源,探索、发现、分享主流开源技术框架,搭建开源技术社区,共创美好开源生态!

Tornado 是一个 Python Web 框架和异步网络库,主要用于处理大量网络请求和数据。Layui 是一个模块化前端 UI 框架,提供了一系列实用的 UI 组件,如表格、分页器、弹出框等。

将 Tornado 与 Layui 结合使用,可以创建一个高效、美观且功能强大的 Web 应用。以下是一个简单的示例,展示如何使用 Tornado 和 Layui 创建一个 Web 应用:

安装 Tornado 和 Layui

首先,确保你已经安装了 Tornado。你可以使用 pip 来安装它:

pip install tornado

创建 Tornado 应用

使用 Tornado 创建一个简单的 Web 应用。例如,创建一个 main.py 文件:

import tornado.ioloop

import tornado.web

from layui import layui_admin

class MainHandler(tornado.web.RequestHandler):

def get(self):

self.write(layui_admin.render('main', 'index')) # 使用 Layui 的渲染方法渲染页面

def make_app():

return tornado.web.Application([

(r"/", MainHandler),

])

if __name__=="__main__":

app=make_app()

app.listen(8888) # 监听端口号,可以根据需要修改

tornado.ioloop.IOLoop.current().start()

创建 Layui 前端页面

在你的项目目录中创建一个 static 文件夹,并在其中创建一个 layui 子文件夹。将 Layui 的 CSS、JS 和其他资源文件放入 layui 文件夹中。然后,创建一个 HTML 文件(例如 index.html),并在其中引入 Layui 的 CSS 和 JS 文件:

<!DOCTYPE html>
<html>
<!-- 头部开始 -->
{% include "public/header.html" %}
<!-- 头部结束 -->
<body>

<!-- 主体部分开始 -->
<div class="layui-fluid">
    <div class="layui-card">
        <div class="layui-card-body">
            <!-- 内容区 -->
            {% block content %}
            {% endblock %}
        </div>
    </div>
</div>
<!-- 主体部分结束 -->

<!-- 脚部开始 -->
{% include "public/footer.html" %}
<!-- 脚部结束 -->
</body>
</html>

运行 Tornado 应用

在终端中运行 Tornado 应用:

python main.py --port=8888 # 根据你的配置修改端口号

路由文件

from apps.views.ad import AdIndexHandler, AdListHandler, AdDetailHandler, AdAddHandler, AdUpdateHandler, \
    AdDeleteHandler, AdStatusHandler
from apps.views.ad_sort import AdSortIndexHandler, AdSortListHandler, AdSortDetailHandler, AdSortAddHandler, \
    AdSortUpdateHandler, AdSortDeleteHandler
from apps.views.analysis import AnalysisIndexHandler
from apps.views.city import CityIndexHandler, CityListHandler, CityDetailHandler, CityAddHandler, CityUpdateHandler, \
    CityDeleteHandler, CityGetChildListHandler
from apps.views.config import ConfigIndexHandler, ConfigListHandler, ConfigDetailHandler, ConfigAddHandler, \
    ConfigUpdateHandler, ConfigDeleteHandler
from apps.views.config_data import ConfigDataIndexHandler, ConfigDataListHandler, ConfigDataDetailHandler, \
    ConfigDataAddHandler, ConfigDataUpdateHandler, ConfigDataDeleteHandler
from apps.views.config_web import ConfigWebIndexHandler
from apps.views.dept import DeptIndexHandler, DeptListHandler, DeptDetailHandler, DeptAddHandler, DeptUpdateHandler, \
    DeptDeleteHandler
from apps.views.dicts import DictIndexHandler, DictListHandler, DictDetailHandler, DictAddHandler, DictUpdateHandler, \
    DictDeleteHandler
from apps.views.dicts_data import DictDataIndexHandler, DictDataListHandler, DictDataDetailHandler, DictDataAddHandler, \
    DictDataUpdateHandler, DictDataDeleteHandler
from apps.views.index import IndexHandler, MainHandler, UserHandler, UpdatePwdHandler, LogoutHandler
from apps.views.item import ItemIndexHandler, ItemListHandler, ItemDetailHandler, ItemAddHandler, ItemUpdateHandler, \
    ItemDeleteHandler
from apps.views.item_cate import ItemCateIndexHandler, ItemCateListHandler, ItemCateDetailHandler, ItemCateAddHandler, \
    ItemCateUpdateHandler, ItemCateDeleteHandler, ItemCateGetTreeListHandler
from apps.views.level import LevelIndexHandler, LevelListHandler, LevelDetailHandler, LevelAddHandler, \
    LevelUpdateHandler, LevelDeleteHandler, LevelStatusHandler, LevelImportHandler, LevelExportHandler
from apps.views.link import LinkIndexHandler, LinkListHandler, LinkDetailHandler, LinkAddHandler, LinkUpdateHandler, \
    LinkDeleteHandler, LinkStatusHandler
from apps.views.login import LoginHandler, CaptchaHandler
from apps.views.member import MemberIndexHandler, MemberListHandler, MemberDetailHandler, MemberAddHandler, \
    MemberUpdateHandler, MemberDeleteHandler, MemberStatusHandler
from apps.views.member_level import MemberLevelListHandler, MemberLevelDetailHandler, MemberLevelAddHandler, \
    MemberLevelUpdateHandler, MemberLevelDeleteHandler, MemberLevelIndexHandler
from apps.views.menu import MenuIndexHandler, MenuListHandler, MenuDetailHandler, MenuAddHandler, MenuUpdateHandler, \
    MenuDeleteHandler
from apps.views.notice import NoticeListHandler, NoticeDetailHandler, NoticeAddHandler, NoticeUpdateHandler, \
    NoticeDeleteHandler, NoticeIndexHandler

from apps.views.position import PositionListHandler, PositionDetailHandler, PositionAddHandler, PositionUpdateHandler, \
    PositionDeleteHandler, PositionStatusHandler, PositionIndexHandler

from apps.views.role import RoleIndexHandler, RoleListHandler, RoleDetailHandler, RoleAddHandler, RoleUpdateHandler, \
    RoleDeleteHandler, RoleStatusHandler
from apps.views.role_menu import RoleMenuIndexHandler, RoleMenuSaveHandler
from apps.views.upload import UploadHandler, UploadEditHandler
from apps.views.user import UserIndexHandler, UserListHandler, UserDetailHandler, UserAddHandler, UserUpdateHandler, \
    UserDeleteHandler, UserStatusHandler, UserResetPwdHandler

# 定义路由集合
router=list()

# 登录路由
def login_router():
    # 路由配置
    r=[
        (r'/', LoginHandler),
        (r'/login', LoginHandler),
        (r'/captcha', CaptchaHandler),
    ]
    # 路由前缀
    login_r=""
    # 路由数组
    login=[(login_r + v[0], v[1]) for v in r]
    print('登录路由:', login)
    # 返回路由
    return login


# 主页路由
def index_router():
    # 路由配置
    r=[
        (r'/', IndexHandler),
        (r'/index', IndexHandler),
        (r'/main', MainHandler),
        (r'/userInfo', UserHandler),
        (r'/updatePwd', UpdatePwdHandler),
        (r'/logout', LogoutHandler),
    ]
    # 路由前缀
    index_r=""
    # 路由数组
    index=[(index_r + v[0], v[1]) for v in r]
    print('主页路由:', index)
    # 返回路由
    return index


# 上传文件路由
def upload_router():
    # 路由配置
    r=[
        (r'/uploadImage', UploadHandler),
        (r'/uploadEditImage', UploadEditHandler),
    ]
    # 路由前缀
    upload_r="/upload"
    # 路由数组
    upload=[(upload_r + v[0], v[1]) for v in r]
    print('上传文件路由:', upload)
    # 返回路由
    return upload


# 职级路由
def level_router():
    # 路由配置
    r=[
        (r'/index', LevelIndexHandler),
        (r'/list?', LevelListHandler),
        (r'/detail/(\d+)', LevelDetailHandler),
        (r'/add', LevelAddHandler),
        (r'/update', LevelUpdateHandler),
        (r'/delete/(\d+)', LevelDeleteHandler),
        (r'/status', LevelStatusHandler),
        (r'/import', LevelImportHandler),
        (r'/export', LevelExportHandler),
    ]
    # 路由前缀
    level_r="/level"
    # 路由数组
    level=[(level_r + v[0], v[1]) for v in r]
    print('职级路由:', level)
    # 返回路由
    return level


# 岗位路由
def position_router():
    # 路由配置
    r=[
        (r'/index', PositionIndexHandler),
        (r'/list?', PositionListHandler),
        (r'/detail/(\d+)', PositionDetailHandler),
        (r'/add', PositionAddHandler),
        (r'/update', PositionUpdateHandler),
        (r'/delete/(\d+)', PositionDeleteHandler),
        (r'/status', PositionStatusHandler),
    ]
    # 路由前缀
    position_r="/position"
    # 路由数组
    position=[(position_r + v[0], v[1]) for v in r]
    print('岗位路由:', position)
    # 返回路由
    return position


# 部门路由
def dept_router():
    # 路由配置
    r=[
        (r'/index', DeptIndexHandler),
        (r'/list?', DeptListHandler),
        (r'/detail/(\d+)', DeptDetailHandler),
        (r'/add', DeptAddHandler),
        (r'/update', DeptUpdateHandler),
        (r'/delete/(\d+)', DeptDeleteHandler),
    ]
    # 路由前缀
    dept_r="/dept"
    # 路由数组
    dept=[(dept_r + v[0], v[1]) for v in r]
    print('部门路由:', dept)
    # 返回路由
    return dept


# 角色路由
def role_router():
    # 路由配置
    r=[
        (r'/index', RoleIndexHandler),
        (r'/list?', RoleListHandler),
        (r'/detail/(\d+)', RoleDetailHandler),
        (r'/add', RoleAddHandler),
        (r'/update', RoleUpdateHandler),
        (r'/delete/(\d+)', RoleDeleteHandler),
        (r'/status', RoleStatusHandler),
    ]
    # 路由前缀
    role_r="/role"
    # 路由数组
    role=[(role_r + v[0], v[1]) for v in r]
    print('角色路由:', role)
    # 返回路由
    return role


# 角色菜单路由
def role_menu_router():
    # 路由配置
    r=[
        (r'/index/(\d+)', RoleMenuIndexHandler),
        (r'/save', RoleMenuSaveHandler)
    ]
    # 路由前缀
    role_menu_r="/rolemenu"
    # 路由数组
    role_menu=[(role_menu_r + v[0], v[1]) for v in r]
    print('角色菜单路由:', role_menu)
    # 返回路由
    return role_menu


# 菜单路由
def menu_router():
    # 路由配置
    r=[
        (r'/index', MenuIndexHandler),
        (r'/list?', MenuListHandler),
        (r'/detail/(\d+)', MenuDetailHandler),
        (r'/add', MenuAddHandler),
        (r'/update', MenuUpdateHandler),
        (r'/delete/(\d+)', MenuDeleteHandler),
    ]
    # 路由前缀
    menu_r="/menu"
    # 路由数组
    menu=[(menu_r + v[0], v[1]) for v in r]
    print('角色路由:', menu)
    # 返回路由
    return menu


# 用户路由
def user_router():
    # 路由配置
    r=[
        (r'/index', UserIndexHandler),
        (r'/list?', UserListHandler),
        (r'/detail/(\d+)', UserDetailHandler),
        (r'/add', UserAddHandler),
        (r'/update', UserUpdateHandler),
        (r'/delete/(\d+)', UserDeleteHandler),
        (r'/status', UserStatusHandler),
        (r'/resetPwd', UserResetPwdHandler),
    ]
    # 路由前缀
    user_r="/user"
    # 路由数组
    user=[(user_r + v[0], v[1]) for v in r]
    print('用户路由:', user)
    # 返回路由
    return user


# 用户路由
def city_router():
    # 路由配置
    r=[
        (r'/index', CityIndexHandler),
        (r'/list?', CityListHandler),
        (r'/detail/(\d+)', CityDetailHandler),
        (r'/add', CityAddHandler),
        (r'/update', CityUpdateHandler),
        (r'/delete/(\d+)', CityDeleteHandler),
        (r'/getChildList/(\w+)', CityGetChildListHandler),
    ]
    # 路由前缀
    city_r="/city"
    # 路由数组
    city=[(city_r + v[0], v[1]) for v in r]
    print('城市路由:', city)
    # 返回路由
    return city


# 通知路由
def notice_router():
    # 路由配置
    r=[
        (r'/index', NoticeIndexHandler),
        (r'/list?', NoticeListHandler),
        (r'/detail/(\d+)', NoticeDetailHandler),
        (r'/add', NoticeAddHandler),
        (r'/update', NoticeUpdateHandler),
        (r'/delete/(\d+)', NoticeDeleteHandler),
    ]
    # 路由前缀
    notice_r="/notice"
    # 路由数组
    notice=[(notice_r + v[0], v[1]) for v in r]
    print('通知路由:', notice)
    # 返回路由
    return notice


# 站点路由
def item_router():
    # 路由配置
    r=[
        (r'/index', ItemIndexHandler),
        (r'/list?', ItemListHandler),
        (r'/detail/(\d+)', ItemDetailHandler),
        (r'/add', ItemAddHandler),
        (r'/update', ItemUpdateHandler),
        (r'/delete/(\d+)', ItemDeleteHandler),
    ]
    # 路由前缀
    item_r="/item"
    # 路由数组
    item=[(item_r + v[0], v[1]) for v in r]
    print('站点路由:', item)
    # 返回路由
    return item


# 站点路由
def item_cate_router():
    # 路由配置
    r=[
        (r'/index', ItemCateIndexHandler),
        (r'/list?', ItemCateListHandler),
        (r'/detail/(\d+)', ItemCateDetailHandler),
        (r'/add', ItemCateAddHandler),
        (r'/update', ItemCateUpdateHandler),
        (r'/delete/(\d+)', ItemCateDeleteHandler),
        (r'/getCateTreeList/(\d+)', ItemCateGetTreeListHandler),
    ]
    # 路由前缀
    item_cate_r="/itemcate"
    # 路由数组
    item_cate=[(item_cate_r + v[0], v[1]) for v in r]
    print('栏目路由:', item_cate)
    # 返回路由
    return item_cate


# 友链路由
def link_router():
    # 路由配置
    r=[
        (r'/index', LinkIndexHandler),
        (r'/list?', LinkListHandler),
        (r'/detail/(\d+)', LinkDetailHandler),
        (r'/add', LinkAddHandler),
        (r'/update', LinkUpdateHandler),
        (r'/delete/(\d+)', LinkDeleteHandler),
        (r'/status', LinkStatusHandler),
    ]
    # 路由前缀
    link_r="/link"
    # 路由数组
    link=[(link_r + v[0], v[1]) for v in r]
    print('友链路由:', link)
    # 返回路由
    return link


# 广告位路由
def ad_sort_router():
    # 路由配置
    r=[
        (r'/index', AdSortIndexHandler),
        (r'/list?', AdSortListHandler),
        (r'/detail/(\d+)', AdSortDetailHandler),
        (r'/add', AdSortAddHandler),
        (r'/update', AdSortUpdateHandler),
        (r'/delete/(\d+)', AdSortDeleteHandler),
    ]
    # 路由前缀
    ad_sort_r="/adsort"
    # 路由数组
    ad_sort=[(ad_sort_r + v[0], v[1]) for v in r]
    print('广告位路由:', ad_sort)
    # 返回路由
    return ad_sort


# 广告路由
def ad_router():
    # 路由配置
    r=[
        (r'/index', AdIndexHandler),
        (r'/list?', AdListHandler),
        (r'/detail/(\d+)', AdDetailHandler),
        (r'/add', AdAddHandler),
        (r'/update', AdUpdateHandler),
        (r'/delete/(\d+)', AdDeleteHandler),
        (r'/status', AdStatusHandler),
    ]
    # 路由前缀
    ad_r="/ad"
    # 路由数组
    ad=[(ad_r + v[0], v[1]) for v in r]
    print('广告路由:', ad)
    # 返回路由
    return ad


# 会员等级路由
def member_level_router():
    # 路由配置
    r=[
        (r'/index', MemberLevelIndexHandler),
        (r'/list?', MemberLevelListHandler),
        (r'/detail/(\d+)', MemberLevelDetailHandler),
        (r'/add', MemberLevelAddHandler),
        (r'/update', MemberLevelUpdateHandler),
        (r'/delete/(\d+)', MemberLevelDeleteHandler),
    ]
    # 路由前缀
    member_level_r="/memberlevel"
    # 路由数组
    member_level=[(member_level_r + v[0], v[1]) for v in r]
    print('会员等级路由:', member_level)
    # 返回路由
    return member_level


# 会员路由
def member_router():
    # 路由配置
    r=[
        (r'/index', MemberIndexHandler),
        (r'/list?', MemberListHandler),
        (r'/detail/(\d+)', MemberDetailHandler),
        (r'/add', MemberAddHandler),
        (r'/update', MemberUpdateHandler),
        (r'/delete/(\d+)', MemberDeleteHandler),
        (r'/status', MemberStatusHandler),
    ]
    # 路由前缀
    member_r="/member"
    # 路由数组
    member=[(member_r + v[0], v[1]) for v in r]
    print('会员路由:', member)
    # 返回路由
    return member


# 字典路由
def dict_router():
    # 路由配置
    r=[
        (r'/index', DictIndexHandler),
        (r'/list?', DictListHandler),
        (r'/detail/(\d+)', DictDetailHandler),
        (r'/add', DictAddHandler),
        (r'/update', DictUpdateHandler),
        (r'/delete/(\d+)', DictDeleteHandler),
    ]
    # 路由前缀
    dict_r="/dict"
    # 路由数组
    dict=[(dict_r + v[0], v[1]) for v in r]
    print('字典路由:', dict)
    # 返回路由
    return dict


# 字典数据路由
def dict_data_router():
    # 路由配置
    r=[
        (r'/index', DictDataIndexHandler),
        (r'/list?', DictDataListHandler),
        (r'/detail/(\d+)', DictDataDetailHandler),
        (r'/add', DictDataAddHandler),
        (r'/update', DictDataUpdateHandler),
        (r'/delete/(\d+)', DictDataDeleteHandler),
    ]
    # 路由前缀
    dict_data_r="/dictdata"
    # 路由数组
    dict_data=[(dict_data_r + v[0], v[1]) for v in r]
    print('字典数据路由:', dict_data)
    # 返回路由
    return dict_data


# 配置路由
def config_router():
    # 路由配置
    r=[
        (r'/index', ConfigIndexHandler),
        (r'/list?', ConfigListHandler),
        (r'/detail/(\d+)', ConfigDetailHandler),
        (r'/add', ConfigAddHandler),
        (r'/update', ConfigUpdateHandler),
        (r'/delete/(\d+)', ConfigDeleteHandler),
    ]
    # 路由前缀
    config_r="/config"
    # 路由数组
    config=[(config_r + v[0], v[1]) for v in r]
    print('配置路由:', config)
    # 返回路由
    return config


# 配置数据路由
def config_data_router():
    # 路由配置
    r=[
        (r'/index', ConfigDataIndexHandler),
        (r'/list?', ConfigDataListHandler),
        (r'/detail/(\d+)', ConfigDataDetailHandler),
        (r'/add', ConfigDataAddHandler),
        (r'/update', ConfigDataUpdateHandler),
        (r'/delete/(\d+)', ConfigDataDeleteHandler),
    ]
    # 路由前缀
    config_data_r="/configdata"
    # 路由数组
    config_data=[(config_data_r + v[0], v[1]) for v in r]
    print('配置数据路由:', config_data)
    # 返回路由
    return config_data


# 网站配置路由
def config_web_router():
    # 路由配置
    r=[
        (r'/index', ConfigWebIndexHandler),
    ]
    # 路由前缀
    config_web_r="/configweb"
    # 路由数组
    config_web=[(config_web_r + v[0], v[1]) for v in r]
    print('网站配置路由:', config_web)
    # 返回路由
    return config_web


# 数据统计路由
def analysis_router():
    # 路由配置
    r=[
        (r'/index', AnalysisIndexHandler),
    ]
    # 路由前缀
    analysis_r="/analysis"
    # 路由数组
    analysis=[(analysis_r + v[0], v[1]) for v in r]
    print('数据统计路由:', analysis)
    # 返回路由
    return analysis


# 初始化路由
def init_routers():
    print('初始化路由')
    # 登录路由
    router.extend(login_router())
    # 主页路由
    router.extend(index_router())
    # 上传文件路由
    router.extend(upload_router())
    # 职级路由
    router.extend(level_router())
    # 岗位路由
    router.extend(position_router())
    # 部门路由
    router.extend(dept_router())
    # 角色路由
    router.extend(role_router())
    # 角色菜单路由
    router.extend(role_menu_router())
    # 菜单路由
    router.extend(menu_router())
    # 用户路由
    router.extend(user_router())
    # 城市路由
    router.extend(city_router())
    # 通知路由
    router.extend(notice_router())
    # 站点路由
    router.extend(item_router())
    # 栏目路由
    router.extend(item_cate_router())
    # 友链路由
    router.extend(link_router())
    # 广告位路由
    router.extend(ad_sort_router())
    # 广告路由
    router.extend(ad_router())
    # 会员等级路由
    router.extend(member_level_router())
    # 会员路由
    router.extend(member_router())
    # 字典路由
    router.extend(dict_router())
    # 字典数据路由
    router.extend(dict_data_router())
    # 配置路由
    router.extend(config_router())
    # 配置数据路由
    router.extend(config_data_router())
    # 网站配置路由
    router.extend(config_web_router())
    # 数据统计路由
    router.extend(analysis_router())
    # 返回结果
    return router

模型文件

from sqlalchemy import Column, String, Integer

from apps.models.base_db import base_db
from apps.models.base_model import base_model
from config.env import DB_PREFIX


# 职级模型
class Level(base_model, base_db):
    # 设置表名
    __tablename__=DB_PREFIX + "level"
    # 职级名称
    name=Column(String(255), nullable=False, comment="职级名称")
    # 职级状态:1-在用 2-停用
    status=Column(Integer, default=0, comment="职级状态:1-在用 2-停用")
    # 职级排序
    sort=Column(Integer, default=0, comment="职级排序")

    # 初始化
    def __init__(self, id, name, status, sort):
        self.id=id
        self.name=name
        self.status=status
        self.sort=sort

    def __repr__(self):
        return '职级:{}'.format(self.name)

模块案例

<!-- 继承layout.html模板 -->
{% extends "public/layout.html" %}
{% block content %}
    <!-- 引入全局自定义组件 -->
    <!-- 功能操作区一 -->
    <form class="layui-form toolbar">
        <div class="layui-form-item">
            <div class="layui-inline">
                <label class="layui-form-label w-auto">职级名称:</label>
                <div class="layui-input-inline">
                    <input type="text" name="name" placeholder="请输入职级名称" autocomplete="off" class="layui-input">
                </div>
            </div>
            <div class="layui-inline">
                <div class="layui-input-inline" style="width: auto;">
                    {{ "查询"|query }}
                    {{ "添加职级"|add("{}") }}
                    {{ "批量删除"|dall }}
                </div>
            </div>
        </div>
    </form>

    <!-- TABLE渲染区 -->
    <table class="layui-hide" id="tableList" lay-filter="tableList"></table>

    <!-- 操作功能区二 -->
    <script type="text/html" id="toolBar">
        {{ "编辑"|edit }}
        {{ "删除"|delete }}
    </script>
{% endblock %}

案例分享

DjangoAdmin敏捷开发框架

使用parse_command_line()后 会影响服务器端日志的输出。tornado会默认为我们配置logging模块

如果想关闭配置用 tornado.options.options.logging=None

* get请求字符串参数传递

1. get请求传给后端 key1=value1&key2=value2

get_query_argument()

get_query_arguments()

2. 请求体数据传递

get_body_argument()

get_body_arguments()

3.既能接收get请求命令内容也能接收post body提交内容

get_argument()

get_arguments()

* post请求体 表单数据 json

* 提取url的指定部分

#无命名子组 按照位置关系传递

(r'/sub-city/(.+)/([a-z]+)',SubjectCityHandler),

#命名子组按照形参名称传递

(r'/sub-city/(?P<subject>.+)/(?P<date>\d+)',\

SubjectDateHandler),

子组中匹配的内容会自动传递个具体的请求处理函数

* 通过http请求头提交自定义字段

import json

json.loads(s) 将json ---》 python字典

json.dumps(d) 将python字典 --- 》 json

***********************************************

1. tornado的安装

2. settings 的设置

3. url的配置

4. 请求数据如何传递给tornado处理

* get ---》参数 key1=1&key2=2

* post ---》提交数据 (表单提交

json (request.body) 文件)

* header ---> 自定义 (request.headers)

+++++++++++++++++++++++++++++++++++++++++++++++++

Response 响应

self.write()

*将一个字符串返回给客户端

*write可以连续多次使用,现将内容写入缓存,然后再一起response到客户端

响应头 :

self.set_header()

*设置一个响应头

set_default_headers()

* 设置默认响应头

* 如果具体方法中也设置了和default 相同的header则以具体方法中的为准

set_status(status_code,reason=None)

*设置响应码

* 响应码的设置不影响正常的网页访问,只影响返回的响应码和提示内容

*当设置未定义的响应码时,必须要加第二个参数

抛出错误

send_error(status,content)

* 引发一个错误

* 如果没有write_error 则直接response一个对应status的默认界面

*在send_error后不能再write写入内容

write_error(self,status_code,**kwargs)

* 处理send_error 抛出的异常

* 会自动将send_error抛出的内容传递给status_code参数

Handler中函数

initialize()

write_error()

set_default_headers()

get() post() head()....

prepare() : 预处理函数 在执行对应的HTTP请求函数前 执行,无论何种HTTP请求都会引起执行

on_finish() : 请求处理后执行,主要用来后续资源释放,日志管理等。此方法中不宜再输出内容

执行顺序(没有异常抛出)

执行了 set_default_error

执行了initialize

执行了prepare

执行了 get请求

执行了on_finish

执行顺序(抛出异常时)

执行了 set_default_error

执行了initialize

执行了prepare

执行了 get请求

执行了 set_default_error

执行了 write_error

执行了on_finish

页面跳转

redirect(url)

模板

1. 模板路径配置 Application中 template_path 赋值表示模板查找路径

2. 模板的查找原则 : 找到符合加载的第一个模板

3. 模板加载函数

render('index.html',**kwargs)

* 变量

render('index.html',a=1,b=2)

+ 如果变量没定义,会报错

列表取值 <p>{{l[2]}}</p>

字典取值 <p>{{d['title']}}</p>

object 取值 <p>{{obj.arg}}</p>

* 表达式

* 控制语句

* 函数

* UIModule

* 静态文件

作业 : 1.总结request 和response 的用法,特别是函 数功能使用

2.复习mysql中sql语句

3.参照之前django的界面项目自己用tornado尝试实现