使用Python的Tornado框架實現(xiàn)一個Web端圖書展示頁面
首先,為什么選擇Tornado:
1.高性能的網(wǎng)絡(luò)庫,這可以和gevent,twisted,libevent等做對。
提供了異步io支持,超時事件處理,在此基礎(chǔ)上提供了tcpserver,httpclient,尤其是curlhttpclient,
在現(xiàn)有http客戶端中肯定排第一。可以用來做爬蟲,游戲服務(wù)器,據(jù)我所知業(yè)界已有使用tornado作為游戲服務(wù)器
2.web框架,這可以和django,flask對。
提供了路由,模板等web框架必備組件。與其他區(qū)別是tornado是異步的,天然適合長輪訓(xùn),
這也是friendfeed發(fā)明tornado的原因,當(dāng)前flask也可以支持,但必須借助gevent等
3.較為完備的http服務(wù)器,這點(diǎn)可以和nginx,apache對比,
但只支持http1.0,所以使用nginx做前段不僅是為了更好利用多核,也是讓其支持http1.1
4.完備的wsgi服務(wù)器,這可以和gunicore,gevent wsgi server做對比,
也就是說可以讓flask運(yùn)行在tornado之上,讓tornado加速flask
5.提供了完備的websocket支持,這讓html5的游戲等提供了便利。
像知乎長輪訓(xùn)就是使用了websocket,但websocket手機(jī)支持的不是很好,
前段時間不得不使用定時ajax發(fā)送大量請求,期待手機(jī)瀏覽器趕快奮起直追
使用tornado創(chuàng)建一個簡單的圖書介紹頁
好了,言歸正傳,下面我們來看一下這個圖書介紹頁的代碼實現(xiàn):
1.創(chuàng)建一個web服務(wù)的入口文件 blockmain.py
#coding:utf-8 import tornado.web import tornado.httpserver import tornado.ioloop import tornado.options import os.path import json import urllib2 from tornado.options import define, options define("port", default=8000, help="run on the given port", type=int) class MainHandler(tornado.web.RequestHandler): def get(self): self.render( "index.html", page_title = "Burt's Books ¦ Home", header_text = "Welcome to Burt's Books!", books = ['細(xì)說php','python','PHP','小時代'] ) class HelloModule(tornado.web.UIModule): def render(self): return'<h1>I am yyx and this is an information from module hello!</h1>' class BookModule(tornado.web.UIModule): def render(self,bookname): doubanapi = r'https://api.douban.com/v2/book/' searchapi = r'https://api.douban.com/v2/book/search?q=' searchurl = searchapi+bookname searchresult = urllib2.urlopen(searchurl).read() bookid = json.loads(searchresult)['books'][0]['id'] bookurl = doubanapi+bookid injson = urllib2.urlopen(bookurl).read() bookinfo = json.loads(injson) return self.render_string('modules/book.html',book = bookinfo) def embedded_javascript(self): return "document.write(\"hi!\")" def embedded_css(self): return '''.book {background-color:#F5F5F5} .book_body{color:red} ''' def html_body(self): return '<script>document.write("Hello!")</script>' if __name__ == "__main__": tornado.options.parse_command_line() app = tornado.web.Application( handlers = [ (r'/',MainHandler), ], template_path = os.path.join(os.path.dirname(__file__),'templates'), static_path = os.path.join(os.path.dirname(__file__),'static'), debug = True, ui_modules={'Hello':HelloModule,'Book':BookModule} ) http_server = tornado.httpserver.HTTPServer(app) http_server.listen(options.port) tornado.ioloop.IOLoop.instance().start()
說明一下,一些基本的MVC概念:
tornado也是通過pathinfo模式來匹配用戶的輸入來獲得參數(shù),然后再調(diào)用相應(yīng)的處理函數(shù),它是通過為各種匹配模式設(shè)定相應(yīng)的class類來處理,比如我這里就是通過class MainHandler來處理來自/的get請求
MainHandler把請求render渲染到index.html,參數(shù)在index.html中通過{{參數(shù)}}來調(diào)用
2.建立相應(yīng)的模板,先創(chuàng)建一個基礎(chǔ)的父類main.html模板,創(chuàng)建templates目錄,在它下面創(chuàng)建main.html,這個模板只是定義了最基礎(chǔ)的網(wǎng)頁框架,里面的具體內(nèi)容由繼承于它的子類來具體實現(xiàn)
<html> <head> <title>{{ page_title }}</title> <link rel="stylesheet" href="{{ static_url("css/style.css") }}" /> </head> <body> <div id="container"> <header> {% block header %}<h1>Burt's Books</h1>{% end %} </header> <div id="main"> <div id="content"> {% block body %}{% end %} </div> </div> <footer> {% set mailLink = '<a href="mailto:contact@burtsbooks.com">Contact Us</a>' %} {% set script = '<script>alert("hello")</script>' %} {% block footer %} <p> For more information about our selection, hours or events, please email us at{% raw mailLink %} <!-- {% raw script %} 這里將原樣輸出,也就是會彈一個框--> </p> {% end %} </footer> </div> <script src="{{ static_url("js/script.js") }}"></script> </body> </html>
這里是定義了一個主框架,其中里面的{% block header %}<h1>Burt's Books</h1>{% end %}是為了子類模板的繼承的塊(block),當(dāng)子類繼承了這個main.html,具體這個塊里寫什么內(nèi)容由子類來實現(xiàn),不實現(xiàn)的話就使用父類的默認(rèn) 值,如是這里的<h1>Burt's Books</h1>,MainHandler類是render到一個index.html,那么接下來寫一個index.html來繼承這 個父類
{% extends "main.html" %} {% block header %} <h1>{{ header_text }}</h1> {% end %} {% block body %} <div id="hello"> <p>Welcome to Burt's Books!</p> {% module Hello() %} {% for book in books %} {% module Book(book) %} {% end %} <p>...</p> </div> {% end %}
簡單簡潔吧,這也是使用了繼承的好處,不用再重復(fù)寫父類的東西,只要實現(xiàn)父類的block內(nèi)容即可
MainHandler類里的render方法中的參數(shù)
page_title = "Burt's Books | Home", header_text = "Welcome to Burt's Books!", books = ['細(xì)說php','python','PHP','小時代']
將會通過參數(shù)傳送到這里來
tornado的模板里可以使用python的代碼,加上{% %}當(dāng)使用if for while等要使用{% end %}結(jié)尾
代碼中{% module Book(book) %} 將會調(diào)用入口服務(wù)文件中的定義和'Book'所對應(yīng)的模塊
ui_modules={'Hello':HelloModule,'Book':BookModule} 也就是BookModule,查看上面的BookModule定義
class BookModule(tornado.web.UIModule): def render(self,bookname): doubanapi = r'https://api.douban.com/v2/book/' searchapi = r'https://api.douban.com/v2/book/search?q=' searchurl = searchapi+bookname searchresult = urllib2.urlopen(searchurl).read() bookid = json.loads(searchresult)['books'][0]['id'] bookurl = doubanapi+bookid injson = urllib2.urlopen(bookurl).read() bookinfo = json.loads(injson) return self.render_string('modules/book.html',book = bookinfo)
BookModule 繼承自tornado.web.UIModule,UI模塊的使用是最后render_string()方法來把一個對象渲染到一個模板中去,我這里簡單 的使用了豆瓣的圖書api,先通過search來查詢一下包含關(guān)鍵詞的圖書信息,返回第一條圖書的id,再使用book api來查詢該圖書的具體信息,將這個具體圖書的信息render到對應(yīng)的模板
在templates 目錄下創(chuàng)建modules目錄,再下創(chuàng)建一個book.html,這里是具體的book要顯示的內(nèi)容框架
<div class="book"> <h3 class="book_title">{{ book["title"] }}</h3> <a href="{{book['alt']}}" target="_blank"><p>點(diǎn)擊查看詳情</p></a> {% if book["subtitle"] != "" %} <h4 class="book_subtitle">{{ book["subtitle"] }}</h4> {% end %} <img src="{{ book["images"]["large"] }}" class="book_image"/> <div class="book_details"> <div class="book_date_released">Released: {{ book["pubdate"]}}</div> <h5>Description:</h5> <div class="book_body">{% raw book["summary"] %}</div> </div> </div>
最后的文件目錄結(jié)構(gòu)應(yīng)該是這樣的
├── blockmain.py └── templates ├── index.html ├── main.html └── modules └── book.html
程序的執(zhí)行是這樣的:
先通過路徑‘/'來使用MainHandler類訪問index.html---->index.html繼承自 main.html---->index.html中的{% module Book(book) %}反過來查找blockmain.py中的Book對應(yīng)的ui_modules---->ui_modules中將查詢得到的book對象內(nèi)容渲 染到modules下的book.html中,這樣就把完整的內(nèi)容呈現(xiàn)出來了,沒有做前端…… 通過python blockmain.py啟動服務(wù),通過http://localhost:8000 來訪問得到如下的網(wǎng)頁
相關(guān)文章
分析Python的Django框架的運(yùn)行方式及處理流程
這篇文章主要介紹了分析Python的Django框架的運(yùn)行方式及處理流程,本文對于Django框架的機(jī)制總結(jié)得非常之直觀精煉,極力推薦!需要的朋友可以參考下2015-04-04Pygame Transform圖像變形的實現(xiàn)示例
pygame.transform 模塊允許您對加載、創(chuàng)建后的圖像進(jìn)行一系列操作,比如調(diào)整圖像大小、旋轉(zhuǎn)圖片等操作,感興趣的可以了解一下2021-11-11Python數(shù)據(jù)擬合與廣義線性回歸算法學(xué)習(xí)
這篇文章主要為大家詳細(xì)介紹了Python數(shù)據(jù)擬合與廣義線性回歸算法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-12-12