整合营销服务商

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

免费咨询热线:

Tornado + layui 后台管理系统

Tornado + layui 后台管理系统

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

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敏捷开发框架

.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

ython 的 Tornado 框架,属于 Python 的一个 Web 框架,是由 Python 编写的 Web 服务器兼 Web 应用框架。


Step1:Tornado 是什么

Tornado 是一个基于 Python 的 Web 服务框架和异步网络库。

最早开发于 FriendFeed 公司,通过利用非阻塞网络 I/O, Tornado 可以承载成千上万的活动连接, 完美的实现了长连接, WebSockets, 和其他对于每一位用户来说需要长连接的程序。


Step2:Tornado 有什么优势

Tornado 具有什么样的优点,我们为什么要用它?

? 轻量级 Web 框架

? 异步非阻塞 IO 处理方式

? 出色的抗负载能力

? 优异的处理性能,不依赖多进程/多线程,一定程度上解决 C10K 问题

? WSGI全栈替代产品,推荐同时使用其 Web 框架和 HTTP 服务器


Step3:Tornado 如何安装

pip install tornado 【安装最新稳定版】

pip install tornado==version 【指定版本安装】


Step4:Tornado 核心内容

4.1 Tornado.Web:Tornado 的基础 Web 框架

? RequestHandler:封装对请求处理的所有信息和处理方法

? get/post/..:封装对应的请求方式

? write():封装响应信息,写响应信息的一个方法


4.2 Tornado.ioloop:核心IO循环模块,封装 Linux 的 Epoll 和 BSD 的 kqueue,Tornado 高性能处理的核心。

? current()返回当前线程的 IOLoop 实例对象

? start()启动 IOLoop 实力对象的 IO 循环,开启监听


4.3 HttpServer 监听端口

? tornado.httpserver.HTTPServer(app)

? httpserver.listen(port)


4.4 HttpServer 实现多进程操作

? tornado.httpserver.HTTPServer(app)

? httpserver.bind(port)

? httpserver.start(0/None/<0/num)


Step5:程序结构及说明

Config.py 配置文件:

import os

#参数
param={
    'port':9992,
}

#配置
setting={
    "template_path":os.path.join(os.path.dirname(__file__), "templates"),  # 定义视图页面地址,放 html文件
    "static_path":os.path.join(os.path.dirname(__file__), "static"),  # 定义静态模板,放 css,js等文件
    # "debug":True,  # 是否为debug模式
    "autoescape":None,  # 不设置转义字符
    "autoreload":True,
    "cookie_secret":"QjyutYf0RBW9DRweq4s+TozDU7esgEUTqQy0M6c5II8=",  #安全cookie
    "xsrf_cookies": False,
    "login_url": "/login",
}


Application.py 路由配置文件:

import tornado.web
import Python_Tornoda.config as config
from Python_Tornoda.util import mysqldb
from Python_Tornoda.view.views import MainHandler
from Python_Tornoda.view.views import LoginHandler
from tornado.web import StaticFileHandler
import os

current_path=os.path.dirname(__file__)

class Appliction(tornado.web.Application):
    def __init__(self):
        handers=[
            (r"/index/(?P<page>\d*)", MainHandler),
            (r"/login",LoginHandler),
            (r'^/(.*?)$', StaticFileHandler,{"path": os.path.join(current_path, "templates"), "default_filename": "main.html"}),
        ]
        super(Appliction,self).__init__(handers,**config.setting)


Views.py视图函数文件,以“登录”为示例:

from Python_Tornoda.util.bussiness import get_data,execute_sql
from Python_Tornoda.util.Pagination import Pagination
from tornado.web import RequestHandler
import time

page_num=5 #每页展示的条数

#登录后的主页
class MainHandler(RequestHandler):
    def get(self,page):
        sql1="select id,pms_name,content,status,mark,create_time from tornado_info order by create_time desc"
        itemList=get_data(sql1)
        print(page)
        if(int(page)>len(itemList)//page_num):
            pages=len(itemList)//page_num+1
        elif(int(page)<1):
            pages=1
        else:
            pages=int(page)
        print("ad")

        page_obj=Pagination(pages, len(itemList), page_num)
        current_list=itemList[page_obj.start:page_obj.end]
        print("00000000000")
        print(current_list)
        str_pageCtrl=page_obj.pageCtrl('/index/')
        self.render('info.html', items=current_list, current_page=page_obj.currentPage, pageCtrl=str_pageCtrl, )

class LoginHandler(RegisterHandler):
    def set_default_headers(self):
        print('-----set_default_headers:默认设置----')
        self.set_header('Content-Type', 'application/json')

    def initialize(self):
        print("-----_initialize 初始化操作-----")
        print("-----_初始化数据库连接-----")
        print("-----_初始化打开文件-----")

    def prepare(self):
        print("-----prepare做一些准备工作-----")
        print("-----加载配置项-----")

    def get(self, *args, **kwargs):
        print("----get 请求处理---")
        print("----此处需要根据页面是get请求来进行处理---")
        username=self.get_query_argument("username")
        password=self.get_query_argument("password")
        self.set_secure_cookie(username,password)
        if(username=="1" and password=="1"):
            self.redirect("/index/1")
        else:
            self.render('main.html')

    def post(self,*args,**kwargs):
        print("----post 请求处理---")
        print("----此处需要根据页面是post请求来进行处理---")
        username=self.get_body_argument("username")
        password=self.get_body_argument("password")
        self.set_secure_cookie(username, password)
        if (username=="1" and password=="1"):
            self.redirect("/index/1")
        else:
            self.render('main.html')

    def write_error(self, status_code: int, **kwargs):
        if(status_code==500):
            self.write("the server is wrong")
        elif(status_code==404):
            self.write("it's not found")
        else:
            self.write("the other of error")

    def on_finish(self):
        print("----处理结束,释放资源----")
        print("----释放db连接----")
        print("----关闭文件句柄----")


Server.py 程序入口文件:

import tornado.ioloop
import tornado.web
import Python_Tornoda.application as app
import Python_Tornoda.config as config

if __name__=='__main__':
    print("starting tornado...")
    app=app.Appliction()
    httpServer=tornado.httpserver.HTTPServer(app)
    httpServer.bind(config.param['port'])
    httpServer.start(1)
    tornado.ioloop.IOLoop.current().start()


Step6:前端代码

Login.html:登录页代码

红框中可以看得到是用什么方式提交/login

Index.html: 登录后的主页代码


Step7:页面效果

7.1 登录页面展示如下:

7.2 登录后主页面展示如下:

备注:页面虽然有些简陋,但麻雀虽小,五脏俱全。哈哈~