螞蟻開源,探索、發現、分享主流開源技術框架,搭建開源技術社區,共創美好開源生態!
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
1.1.Tornado的優勢
1.2.Tornado VS Django
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.入門程序代碼解析
4.2.httpserver底層處理
tornado.httpserver.HTTPServer(app)httpserver.listen(port)
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配置
#自動重啟+取消緩存模板+取消緩存靜態文件+提供追蹤信息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_query_arguments(name,default=_ARG_DEFAULT,strip=True) get_query_argument(name ,strip=True)
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
實例
# -*- 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()
.add_header() .set_header().set_default_headers()設置響應HTTP頭, 前兩者的不同點在于多次設置同一個項時,.add_header()會疊加參數, 而.set_header()則以最后一次為準..set_default_headers()比較特殊, 是一個空方法, 可根據需要重寫, 作用是在每次請求初始化RequestHandler時設置默認headers
.
清除指定的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()
.send_error()用于發送HTTP錯誤頁(狀態碼). 該操作會調用.clear().set_status().write_error()用于清除headers, 設置狀態碼, 發送錯誤頁. 重寫.write_error()可以自定義錯誤頁.
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()
數據流
dict, 那Tornado會自動將其識別為json, 并把Content-Type設置為application/json, 如果你不想要這個Content-Type, 那么在.write()之后, 調用.set_header()重新設置就好了. 需要注意的是, 如果直接傳入的是list, 考慮到安全問題(json數組會被認為是一段可執行的JavaScript腳本, 且<script src="*/secret.json">可以繞過跨站限制),list將不會被轉換成json.
.
# -*- 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()
頁面
# 臨時重定向 301self.redirect('/foo')# 永久重定向 302self.redirect('/foo', permanent=True)# 指定狀態碼, 會忽略參數 permanentself.redirect('/foo', status=304)
Tornado 是一個基于 Python 的 Web 服務框架和異步網絡庫。
最早開發于 FriendFeed 公司,通過利用非阻塞網絡 I/O, Tornado 可以承載成千上萬的活動連接, 完美的實現了長連接, WebSockets, 和其他對于每一位用戶來說需要長連接的程序。
Tornado 具有什么樣的優點,我們為什么要用它?
? 輕量級 Web 框架
? 異步非阻塞 IO 處理方式
? 出色的抗負載能力
? 優異的處理性能,不依賴多進程/多線程,一定程度上解決 C10K 問題
? WSGI全棧替代產品,推薦同時使用其 Web 框架和 HTTP 服務器
pip install tornado 【安裝最新穩定版】
pip install tornado==version 【指定版本安裝】
? RequestHandler:封裝對請求處理的所有信息和處理方法
? get/post/..:封裝對應的請求方式
? write():封裝響應信息,寫響應信息的一個方法
? current()返回當前線程的 IOLoop 實例對象
? start()啟動 IOLoop 實力對象的 IO 循環,開啟監聽
? tornado.httpserver.HTTPServer(app)
? httpserver.listen(port)
? tornado.httpserver.HTTPServer(app)
? httpserver.bind(port)
? httpserver.start(0/None/<0/num)
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()
紅框中可以看得到是用什么方式提交/login
備注:頁面雖然有些簡陋,但麻雀雖小,五臟俱全。哈哈~
*請認真填寫需求信息,我們會在24小時內與您取得聯系。