一、綜述
基於興趣嘗試使用Python開發語言搭建一個基礎的web框架,本次採用的方案是集成tornado方式。項目源碼
二、開發環境
系統需要具備以下開發環境:
- Python-3.7 ( Anaconda 2020.02 )
- tornado-6.0.3
- PyCharm開發工具
三、python下載tornado庫
如果當前的環境裏沒有tornado依賴庫,使用以下命令安裝
pip install tornado
四、基於Python3.x搭建web框架
需具備上述開發環境後,方可進入以下搭建流程。推薦使用PyCharm開發工具,也可以使用其他的開發工具替代。
1. 項目目錄介紹
config.py:項目環境的基礎配置文件
application.py:自定義tornado Application啓動類,自定義相關的配置等
server.py:項目的啓動類
views:項目的路由定義及相關業務處理的目錄,類似SpringBoot中的controller
static:該目錄爲項目的靜態資源目錄,用於存放js/css/img等靜態資源
templates:該目錄爲項目的模板頁面資源文件,用於渲染相關的顯示頁面
upfile:該目錄爲項目的文件上傳基礎目錄
2.項目配置文件config.py
該文件統一管理項目的配置文件,包含啓動的端口,tornado支持的一些web啓動配置參數,項目的請求路由註冊等。
import os
"""
#config
配置參數
"""
options = {
"port": 8080
}
"""
#config
配置文件,相當於django裏面的setting
配置application應用程序路由,即文件地址路徑
BASE_DIRS = os.path.dirname(__file__)
當前file文件路徑
##os.path.join(BASE_DIRS,"static")
拼接路徑:如(BASE_DIRS/static),當然BASE_DIRS=當前文件的父類的文件路徑
"""
BASE_DIRS = os.path.dirname(__file__)
print("******config******")
print("BASE_DIRS",BASE_DIRS)
"""
靜態路由配置
"""
STATIC_ROUTERS_CONFIGS = {
"STATIC_PATH":os.path.join(BASE_DIRS,"static"),
"CSS_URL": os.path.join(BASE_DIRS,"static","css"),
"JS_URL":os.path.join(BASE_DIRS,"static","js"),
"IMG_URL":os.path.join(BASE_DIRS,"static","img")
}
"""
tornado配置
"""
settings = {
"static_path": os.path.join(BASE_DIRS, "static"), # 靜態文件
# "static_url_prefix": "/static",
"template_path": os.path.join(BASE_DIRS, "templates"), # 視圖
"compiled_template_cache":True,
"autoescape":None,
"debug": True,
"cookie_secret": "OrGWKG+lTja4QD6jkt0YQJtk+yIUe0VTiy1KaGBIuks",
"xsrf_cookies": True,
"login_url": "/login"
}
3.項目自定義Web Application
- (1)創建MainApplication繼承tornado.web.Application,自定義相關的靜態資源路由配置。
- (2)**all_router_configs()**方法爲抽取的views目錄下定義的路由接口,這樣可以按模塊定義相應的路由和處理的Handler,下面會詳細說到。
import tornado.web
import os
import config
from views import *
from config import settings
from tornado.web import StaticFileHandler,URLSpec
"""
創建Application
"""
class MainApplication(tornado.web.Application):
def __init__(self):
# BASE HANDLERS
handlers = [
# 靜態文件
URLSpec(r"/static/(.*)", StaticFileHandler, {"path": config.STATIC_ROUTERS_CONFIGS["STATIC_PATH"]}),
URLSpec(r"/css/(.*)", StaticFileHandler, {"path": config.STATIC_ROUTERS_CONFIGS["CSS_URL"]}),
URLSpec(r"/js/(.*)", StaticFileHandler, {"path": config.STATIC_ROUTERS_CONFIGS["JS_URL"]}),
URLSpec(r"/img/(.*)", StaticFileHandler, {"path": config.STATIC_ROUTERS_CONFIGS["IMG_URL"]}),
]
# SERVICE HANDLERS
handlers.extend(all_router_configs())
super().__init__(handlers=handlers, **settings)
print("******tornado web application configs******")
print("handlers", handlers)
print("setting", config.settings)
4.項目啓動類server.py
項目的啓動入庫類server.py,啓動命令:python server.py
import tornado.web
import tornado.ioloop
import tornado.httpserver
import tornado.options
import config #導入自定義配合的py文件
import application #導入自定義的應用程序模塊
"""
server服務配置
"""
if __name__ == "__main__":
app = application.MainApplication()
httpServer = tornado.httpserver.HTTPServer(app)
httpServer.bind(config.options["port"])
httpServer.start(1)
print("server success start, port:",config.options["port"])
tornado.ioloop.IOLoop.current().start()
5. views下路由定義介紹
views目錄爲項目所有的路由定義的地方及相關業務處理的模塊,建議按業務模塊化的方式管理。
5.1 自定義路由接口ViewRouterInterface
接口統一定義獲取註冊路由方法,便於獲取每個handler註冊的路由配置。
"""
統一定義路由配置URL
"""
from abc import ABCMeta,abstractmethod
"""
定義公共的路由方法
"""
class ViewRouterInterface(metaclass=ABCMeta):
"""
配置路由,要求返回數組行駛
"""
@abstractmethod
def configRouter(self):
raise NotImplementedError
5.2 views package默認的初始化文件__init__.py
- (1)python中每當導入一個package時會默認先執行相關的__init__.py文件,可以藉此時機獲取項目裏所有註冊的handler。
- (2)ALL_HANDLERS爲項目裏註冊的業務處理Handler,應爲RequestHandler的子類
- (3)all_router_configs方法爲views包下的全局方法,用於獲取每個ALL_HANDLERS裏配置的相關路由和請求處理器。
"""
請求路由定義及相關的業務處理
Handler相當於Web中的Controller
ViewRouterInterface定義了獲取路由配置的統一接口
即configRouter方法返回路由配置數組
"""
print("******start to import view Request Handler packages******")
from views.test.TestHandlerKit import TestHandler
from views.index.index import IndexHandler,LoginHandler
from views.upload.UploadUtilsHandlerKit import UploadFileHandler
# 定義所有的RequestHandler
ALL_HANDLERS = [
TestHandler,IndexHandler,LoginHandler,UploadFileHandler
]
"""
獲取所有的路由
"""
def all_router_configs():
allRouters = []
for viewRouterInterface in ALL_HANDLERS:
routerConfigs = viewRouterInterface.configRouter(viewRouterInterface)
if routerConfigs is None:
continue
allRouters.extend(routerConfigs)
print("ALL ROUTER CONFIGS",allRouters)
return allRouters
5.3 自定義TestHandler
- (1)按照模塊化管理的思想,在views目錄下創建test文件夾,創建TestHandler.py文件。
- (2)TestHandler繼承ViewRouterInterface和RequestHandler類。
- (3)繼承ViewRouterInterface是爲了自定義相關的路由及處理Handler。
- (4)繼承RequestHandler,實現其中的get和post方法用於處理Http的GET請求和POST請求,類似SpringBoot中的Controller。
from tornado.web import RequestHandler
from views.ViewRouterInterface import ViewRouterInterface
"""
Test view
"""
class TestHandler(ViewRouterInterface,RequestHandler):
# 配置路由
def configRouter(self):
return [
(r"/test",TestHandler)
]
# Get方法
def get(self):
items = ["item1", "item2", "item3"]
items2 = ["item1", "item2"]
def checked(item):
return 'checked=checked' if item in items2 else ''
self.render("test/test.html", items=items, add=add, items2=items2, checked=checked)
"""
Html Page Function
"""
def add(x, y):
return (x+y)
5.4自定義test.html模板頁面
- (1)按照模板化管理的思想,建議模板頁面同樣使用模塊化文件夾管理的方式,在templates目錄下創建test目錄。
- (2)創建test.html文件,簡單demo顯示Handler返回的結果及調用Handler裏自定義的函數。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Test1 HTML</title>
</head>
<body>
{% for item in items %}
<li>{{ escape(item) }}</li>
<li>
<input value={{item}} name={{item}} type="checkbox"
{{checked(item)}}
/> {{item}}
</li>
{% end %}
add func test: 2+2={{ add(2,2) }}
</body>
</html>
6.啓動項目
啓動方式:
python server.py
7.訪問請求
五、總結
工作之餘學習瞭解下如何基於python開發語言實現一個web開發框架,若有不足或者錯誤之處,請多多指教!!!