在網上瀏覽網頁,由于現在網速也快了,大概你很少注意網頁中那些所謂的靜態文件。怎么找出來靜態文件呢?
如果使用firefox(我特別向列位推薦這個瀏覽器,它是我認為的最好的瀏覽器,沒有之一。哈哈。“你信不信?反正我信了。”),可以通過firebug組件,來研究網頁的代碼,當然,你直接看源碼也行。
[](https://github.com/qiwsir/ITArticles/blob/master/Pictures/31301.png)
上圖中,我打開了一個對天朝很多人來說不存在的網站,并且通過Firebug查看其源碼,打開``,發現里面有不少`<script`和`<link`開始引入的文件,這些文件一部分是javascript文件,一部分是css文件。在一個網站中,這類文件一般是不會發生變化的,也就是它的內容穩定,直到下次文件管理員或者有權限的人修改時。而網站程序本身一般不會修改它們。因此將他們稱之為**靜態文件**。
此外,網站中的**靜態文件**還包括一些圖片,比如logo,以及做為邊框的圖片等。
在tornado中,有專門方法處理這些靜態文件。
## 靜態路徑
看官是否還記得在前面寫過這個模樣的代碼:`template_path=os.path.join(os.path.dirname(__file__), "templates")`,這里是設置了模板的路徑,放置模板的目錄名稱是`templates`。類似的方法,我們也可以設置好靜態文件的路徑。
~~~
static_path=os.path.join(os.path.dirname(__file__), "static")
~~~
這里的設置,就是將所有的靜態文件,放在了`static`目錄中。
這樣就設置了靜態路徑。
下面的代碼是將[上一節](https://github.com/qiwsir/ITArticles/blob/master/BasicPython/312.md)的代碼進行了改寫,注意變化的地方
~~~
#! /usr/bin/env python
#-*- coding:utf-8 -*-
import os.path
import tornado.httpserver
import tornado.ioloop
import tornado.web
import tornado.options
from tornado.options import define, options
define("port", default=8000, help="run on the given port", type=int)
class IndexHandler(tornado.web.RequestHandler):
def get(self):
lst = ["python","www.itdiffer.com","qiwsir@gmail.com"]
self.render("index.html", info=lst)
handlers = [(r"/", IndexHandler),]
template_path = os.path.join(os.path.dirname(__file__), "temploop")
static_path = os.path.join(os.paht.dirname(__file__), "static") #這里增加設置了靜態路徑
if __name__ == "__main__":
tornado.options.parse_command_line()
app = tornado.web.Application(handlers, template_path, static_path, debug=True) #這里也多了點
http_server = tornado.httpserver.HTTPServer(app)
http_server.listen(options.port)
tornado.ioloop.IOLoop.instance().start()
~~~
上面的代碼比前一講中,多了兩處,一處是定義了靜態文件路徑`static_path`,在這里將存儲靜態文件的目錄命名為`static`。另外一個修改就是在實例化`tornado.web.Application()`的時候,在參數中,出了有靜態路徑參數`static_path`,還有一個參數設置`debug=True`,這個參數設置的含義是當前的tornado服務器可以不用重啟,就能夠體現已經修改的代碼功能。回想一下,在前面進行調試的時候,是不是每次如果修改了代碼,就得重啟tornado服務器,才能看到修改效果。用了這個參數就不用這么麻煩了。
特別說著,`debug=True`僅僅用于開發的調試過程中,如果在生產部署的時候,就不要這么使用了。
## 編寫模板文件
我們設置靜態路徑的目的就是要在模板中引入css和js等類型的文件以及圖片等等。那么如何引入呢,下面以css為例說明。
在一般網頁的`...`部分,都會引入CSS,例如下面的寫法不少網站都愿意引用google的字體庫,樣式如下:
~~~
<link href='http://fonts.googleapis.com/css?family=Open+Sans:300,400,600&subset=latin,latin-ext' rel='stylesheet'>
~~~
這就是CSS的引入。
但是,如果看官在墻內也這么引入字體庫,希望自己的網頁上能使用,那就有點麻煩了,因為google的這個項目已經不行被墻,如果在網頁中寫了上面代碼,會導致網頁打開速度很慢,有的甚至出錯。
怎么辦?那就不用啦。不過,國內有好心網站做了整個谷歌字體的代理,可以用下面方式,墻里面就不怕了。
~~~
<link href='http://fonts.useso.com/css?family=Open+Sans:300,400,600&subset=latin,latin-ext' rel='stylesheet'>
~~~
順便提供一個墻內的常用前端庫地址:[http://libs.useso.com/,供看官參考使用。](http://libs.useso.com/%EF%BC%8C%E4%BE%9B%E7%9C%8B%E5%AE%98%E5%8F%82%E8%80%83%E4%BD%BF%E7%94%A8%E3%80%82)
那么如果我自己寫CSS呢?并且按照前面的設定,已經將該CSS文件放在了static目錄里面,命名為style.css,就可以這樣引入
~~~
<link href="/static/style.css" rel="stylesheet">
~~~
但是,這里往往會有一個不方便的地方,如果我手閑著無聊,或者因為別的充足理由,將存儲靜態文件的目錄static換成了sta,并且假設我已經在好幾個模板中都已經寫了上面的代碼。接下來我就要把這些文件全打開,一個一個更改``里面的地址。
請牢記,凡是遇到重復的事情,一定要找一個函數方法解決。tornado就提供了這么一個:`static_url()`,把上面的代碼寫成:
~~~
<link href="{{ static_url("style.css") }}" rel="stylesheet" >
~~~
這樣,就不管你如何修改靜態路徑,模板中的設置可以不用變。
按照這個引入再修改相應的模板文件。
## 一個項目框架
以上以及此前,我們所有寫過的,都是簡單的技術方法演示,如果要真的寫一個基于tornado框架的網站,一般是不用這樣的直接把代碼都寫到一個文件index.py中的,一個重要原因,就是這樣做不容易以后維護,也不便于多人協作寫一個項目。
所以在真實的項目中,常常要將不同部件寫在不同文件中。下面的例子就是一個項目的基本框架。當然,這還是一個比較小的項目,但是“麻雀雖小,五臟俱全”。
創建一個文件夾,我給它命名為project,在這個文件里面分別創建下面的文件和目錄,文件和目錄里面的內容可以先不用管,“把式把式,先看架勢”,先搭起項目結構來。
* 文件`application.py`:這個文件的核心任務是完成`tornado.web.Application()`的實例化
* 文件`url.py`:在這個文件中記錄項目中所有URL和映射的類,即完成前面代碼中`handlers=[...]`的功能
* 文件`server.py`:這是項目的入口文件,里面包含`if __name__ == "__main__"`,從這里啟動項目和服務
* 目錄handler:存放`.py`文件,即所謂各種請求處理類(當然,如果更大一些的項目,可能還要分配給別的目錄來存儲這種東西)
* 目錄optsql:存放操作數據庫的文件,比如各種讀取或者寫入數據庫的類或函數,都放在這里面的某些文件中
* 目錄static:存放靜態文件,就是上文說的比如CSS,JS,圖片等,為了更清晰,在這個目錄里面,還可建立子目錄,比如我就建立了:css,js,img三個子目錄,分別對應上面的三種。
* 目錄template:存放`.html`的模板(在更大型的項目中,可能會設計多個目錄來存放不同的模板,或者在里面再有子目錄進行區分)
以上就是我規劃的一個項目的基本框架了。不同開發者根據自己的習慣,有不同的規劃,或者有不同的命名,這沒有關系。不過需要說明的,盡量使用名詞(英文)。我看到過有人做過單復數之爭論。我個人認為,這個無所謂,只要在一個項目中一貫就好了。我還是用單數吧,因為總忘記那個復數后面的s
下面分別把不同部分文件的內容列出來,因為都是前面代碼的重復,不過是做了一點從新部署,所以,就不解釋了。個別地方有一點點說明。
文件application.py的代碼如下:
~~~
#!/usr/bin/env python
#coding:utf-8
from url import url
import tornado.web
import os
setting = dict(
template_path=os.path.join(os.path.dirname(__file__),"template"),
static_path=os.path.join(os.path.dirname(__file__),"static"),
)
application = tornado.web.Application(
handlers=url,
**setting
)
~~~
`from url import url`是從文件url.py引入內容
下面看看url.py文件內容:
~~~
#!/usr/bin/env python
#coding:utf-8
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
from handler.index import IndexHandler
url=[
(r'/', IndexHandler),
]
~~~
在這個文件中,從`import sys`開始的三行,主要是為了解決如果文件里面有漢字,避免出現亂碼。現在這個文件很簡單,里面只有`(r'/', IndexHandler)`一條URL,如果多條了,就要說明每條是什么用途,如果用中文寫注釋,需要避免亂碼。
以上兩個預備好了,就開始寫server.py,內容如下:
~~~
#!/usr/bin/env python
#coding:utf-8
import tornado.ioloop
import tornado.options
import tornado.httpserver
import sys
from application import application
from tornado.options import define,options
define("port",default=8888,help="run on th given port",type=int)
def main():
tornado.options.parse_command_line()
http_server = tornado.httpserver.HTTPServer(application)
http_server.listen(options.port)
print 'Development server is running at http://127.0.0.1:%s/' % options.port
print 'Quit the server with Control-C'
tornado.ioloop.IOLoop.instance().start()
if __name__=="__main__":
main()
~~~
這個就不需要解釋了。接下來就看目錄,首先在`static/css/`里面建立一個style.css的文件,并寫樣式表。我只寫了下面的樣式,這個樣式的目的主要是去除瀏覽器默認的樣式,在實際的工程項目中,這個步驟是非常必要的,一定要去除所有默認的樣式,然后重新定義,才能便于控制。
~~~
html, body, div, span, applet, object, iframe,h1, h2, h3, h4, h5, h6, p, blockquote, pre,a, abbr, acronym, address, big, cite, code,del, dfn, em, img, ins, kbd, q, s, samp,small, strike, strong, sub, sup, tt, var,b, u, i, center,dl, dt, dd, ol, ul, li,fieldset, form, label, legend,table, caption, tbody, tfoot, thead, tr, th, td,article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary,time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section {
display: block;
}
body {
/* standard body */
margin: 0 auto;
width: 960px;
font: 14px/20px "Trebuchet MS", Verdana, Helvetica, Arial, sans-serif;
}
~~~
為了能夠在演示的時候看出樣式控制的變化,多寫了一個對body的控制,居中且寬度為960px。
樣式表已經定義好,就要看`template/index.html`了,這個文件就是本項目中的唯一一個模板。
~~~
<DOCTYPE html>
<html>
<head>
<title>Loop in template</title>
<link rel="stylesheet" type="text/css" href="{{ static_url('css/style.css')}}">
</head>
<body>
<h1>aaaAAA</h1>
<p>There is a list, it is <b>{{info}}</b></p>
<p>I will print the elements of this list in order.</p>
{% for element in info %}
<p>{{element}}</p>
{% end %}
<br>
{% for index,element in enumerate(info) %}
<p>info[{{index}}] is {{element}}
{% if element == "python" %}
<p> <b>I love this language--{{element}}</b></p>
{% end %}
{% end %}
{% if "qiwsir@gmail.com" in info %}
<p><b>A Ha, this the python lesson of LaoQi, It is good! His email is {{info[2]}}</b></p>
{% end %}
<h2>Next, I set "python-tornado"(a string) to a variable(var)</h2>
{% set var="python-tornado" %}
<p>Would you like {{var}}?</p>
</body>
</html>
~~~
在這個文件中,特別注意就是`<link rel="stylesheet" type='text/css' href="{{ static_url('css/style.css')}}"`,這里引入了前面定義的樣式表文件。引入方式就是前文講述的方式,不過由于是在css這個子目錄里面,所以寫了相對路徑。
行文到此,我原以為已經完成了。一檢查,發現一個重要的目錄`handler`里面還空著呢,那里面放index.py文件,這個文件里面是請求響應的類IndexHandler
~~~
#!/usr/bin/env python
#coding:utf-8
import tornado.web
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
class IndexHandler(tornado.web.RequestHandler):
def get(self):
lst = ["python","www.itdiffer.com","qiwsir@gmail.com"]
self.render("index.html", info=lst)
~~~
這個文件的代碼沒有什么增加的內容,只是多了三行設置為utf-8的配置,目的是避免漢字亂碼。另外,很需要說明的是,由于這個文件在handler目錄里面,要在上一層的url.py中引用(看url.py內容),必須要在本目錄中建立一個名稱是`__init__.py`的空文。
好了,基本結構已經完成。跑起來。效果就是這樣的:
[](https://github.com/qiwsir/ITArticles/blob/master/Pictures/31302.png)
- 第零部分 獨上高樓,望盡天涯路
- 嘮叨一些關于Python的事情
- 為什么要開設本欄目
- 第一部分 積小流,至江海
- Python環境安裝
- 集成開發環境(IDE)
- 數的類型和四則運算
- 啰嗦的除法
- 開始真正編程
- 初識永遠強大的函數
- 玩轉字符串(1):基本概念、字符轉義、字符串連接、變量與字符串關系
- 玩轉字符串(2)
- 玩轉字符串(3)
- 眼花繚亂的運算符
- 從if開始語句的征程
- 一個免費的實驗室
- 有容乃大的list(1)
- 有容乃大的list(2)
- 有容乃大的list(3)
- 有容乃大的list(4)
- list和str比較
- 畫圈還不簡單嗎
- 再深點,更懂list
- 字典,你還記得嗎?
- 字典的操作方法
- 有點簡約的元組
- 一二三,集合了
- 集合的關系
- Python數據類型總結
- 深入變量和引用對象
- 賦值,簡單也不簡單
- 坑爹的字符編碼
- 做一個小游戲
- 不要紅頭文件(1): open, write, close
- 不要紅頭文件(2): os.stat, closed, mode, read, readlines, readline
- 第二部分 窮千里目,上一層樓
- 正規地說一句話
- print能干的事情
- 從格式化表達式到方法
- 復習if語句
- 用while來循環
- 難以想象的for
- 關于循環的小伎倆
- 讓人歡喜讓人憂的迭代
- 大話題小函數(1)
- 大話題小函數(2)
- python文檔
- 重回函數
- 變量和參數
- 總結參數的傳遞
- 傳說中的函數條規
- 關于類的基本認識
- 編寫類之一創建實例
- 編寫類之二方法
- 編寫類之三子類
- 編寫類之四再論繼承
- 命名空間
- 類的細節
- Import 模塊
- 模塊的加載
- 私有和專有
- 折騰一下目錄: os.path.<attribute>
- 第三部分 昨夜西風,亭臺誰登
- 網站的結構:網站組成、MySQL數據庫的安裝和配置、MySQL的運行
- 通過Python連接數據庫:安裝python-MySQLdb,連接MySQL
- 用Pyton操作數據庫(1):建立連接和游標,并insert and commit
- 用Python操作數據庫(2)
- 用Python操作數據庫(3)
- python開發框架:框架介紹、Tornado安裝
- Hello,第一個網頁分析:tornado網站的基本結構剖析:improt模塊、RequestHandler, HTTPServer, Application, IOLoop
- 實例分析get和post:get()通過URL得到數據和post()通過get_argument()獲取數據
- 問候世界:利用GAE建立tornado框架網站
- 使用表單和模板:tornado模板self.render和模板變量傳遞
- 模板中的語法:tornado模板中的for,if,set等語法
- 靜態文件以及一個項目框架
- 模板轉義
- 第四部分 暮然回首,燈火闌珊處
- requests庫
- 比較json/dictionary的庫
- defaultdict 模塊和 namedtuple 模塊
- 第五部分 Python備忘錄
- 基本的(字面量)值
- 運算符
- 常用的內建函數
- 擴展閱讀(來自網絡文章)
- 人生苦短,我用Python