otherrrr@gmail.com原創(chuàng),轉(zhuǎn)載請(qǐng)注明原作者地址:otherrrr 的百度空間。
注:本文針對(duì)web.py 0.23版,以及python 2.5.1;
如果您使用web.py 0.1x版,或python 2.4.x,
那么有些功能會(huì)有所不同
01、準(zhǔn)備工作
先安裝Python,然后安裝web.py。
不會(huì)安裝的朋友,參考本博客的其他文章。
數(shù)據(jù)庫(kù)我準(zhǔn)備使用Python自帶的sqlite,因此不用另安裝其他數(shù)據(jù)庫(kù)。
(我的運(yùn)行環(huán)境是在Windows 2003下面,因?yàn)镻ython是跨平臺(tái)的,所以理論上在Linux下面一樣可行,但是我沒(méi)有測(cè)試)
當(dāng)前程序版本:Python 2.5.1,web.py 0.23。
(Python的官方網(wǎng)站:http://www.)
(web.py的官方網(wǎng)站:http://)
02、數(shù)據(jù)庫(kù)
數(shù)據(jù)庫(kù)我是用sqlite,主要是我并不會(huì)做一個(gè)大大大大的blog,用mysql是不是太浪費(fèi)了?
而且sqlite現(xiàn)在python也集成了,用起來(lái)很方便。
(當(dāng)然也可以用mysql,很流行的,如果想使用mysql的話,請(qǐng)搜一下“MySQLdb”)
(在web.py 0.23版本中,目前只支持3種數(shù)據(jù)庫(kù):postgres、mysql、sqlite)
那么不用數(shù)據(jù)庫(kù)可不可以?當(dāng)然可以。我其實(shí)很喜歡用txt文件,呵呵。
但是大家都用,我們最好也用。
(很久很久之后的將來(lái),你會(huì)發(fā)現(xiàn)用數(shù)據(jù)庫(kù)的好處)
我創(chuàng)建一個(gè)Python源程序文件:database.py,然后寫(xiě)一些代碼來(lái)創(chuàng)建一個(gè)數(shù)據(jù)庫(kù),并插入一些文件。
代碼如下:
# -*- coding: cp936 -*-
import sqlite3 # 導(dǎo)入sqlite模塊
con = sqlite3.connect("blog.db") # 連接到數(shù)據(jù)庫(kù)文件
cur = con.cursor() # 創(chuàng)建一個(gè)指針
cur.execute("create table user1 (date, number, article)") # 創(chuàng)建1個(gè)表格,并創(chuàng)建3個(gè)域
tt1 = (’2007-10-11′, ’1′, ‘aaa’) # 準(zhǔn)備要插入的數(shù)據(jù)
cur.execute("""insert into user1 (date, number, article) values(?,?,?)""", tt1) # 插入數(shù)據(jù)
tt2 = (’2008-01-19′, ’2′, ‘bbbbb’) # 再插入一組數(shù)據(jù)
cur.execute("""insert into user1 (date, number, article) values(?,?,?)""", tt2)
tt3 = (’1997-03-25′, ’3′, ‘cc’) # 再再插入一組數(shù)據(jù)
cur.execute("""insert into user1 (date, number, article) values(?,?,?)""", tt3)
con.commit() # 執(zhí)行操作
cur.close() # 關(guān)閉指針
con.close() # 關(guān)閉數(shù)據(jù)庫(kù)連接
如果你會(huì)SQL的話上面的東西就很好理解,不會(huì)的的話,也很好理解,是不是?
數(shù)據(jù)庫(kù)的連接——關(guān)閉,指針的創(chuàng)建——關(guān)閉,先建立一個(gè)表格,表格中有域,可以插入數(shù)據(jù)。
(你用過(guò)Excel沒(méi)有?差不多都是一樣的)
有可能你不太理解為什么要把插入的數(shù)據(jù)寫(xiě)成(’2007-10-11′, ’1′, ‘aaa’)這樣的。
這樣的數(shù)據(jù)結(jié)構(gòu)是一個(gè)tuple(元祖),據(jù)說(shuō)這樣可以防止“數(shù)據(jù)庫(kù)的注入式漏洞”。
好了,運(yùn)行一下database.py吧,會(huì)在同目錄下出現(xiàn)一個(gè)文件“blog.db”。這就是我們的數(shù)據(jù)庫(kù)!
(最好能看一下Python Library Reference的13.13 sqlite3 — DB-API 2.0 interface for SQLite databases)
(這里面會(huì)對(duì)python里面內(nèi)置的sqlite3做一個(gè)簡(jiǎn)單但是非常有用的介紹)
03、第一個(gè)頁(yè)面
我們現(xiàn)在來(lái)寫(xiě)第一個(gè)頁(yè)面,看看web.py到底能不能跑起來(lái)。
代碼如下:
import web
urls = (
‘/’, ‘index’,
)
class index:
def GET(self):
print ‘index’
if __name__ == "__main__":
web.run(urls, globals())
保存為:blog_1.py。并運(yùn)行之。
注意:一定要在命令提示符下運(yùn)行!
可以在命令提示符下面看到:http://0.0.0.0:8080/,
打開(kāi)IE,訪問(wèn):http://127.0.0.1:8080/,
可以看到“index”了,是不是?
04、整體架構(gòu)
現(xiàn)在讓我們冷靜一下,先想想我們要做的這個(gè)Blog的整體架構(gòu)。
雖然我們要做個(gè)最最最簡(jiǎn)單的Blog,但是還是要先想好然后再動(dòng)手。
首先,要能“顯示”,能顯示每個(gè)用戶的文章、序號(hào)、以及日期。
然后,要能“登陸”,只有“登陸”之后才能“寫(xiě)文章”。
我就想到這兩點(diǎn),我認(rèn)為這就是一個(gè)blog的雛形了。
那么我們需要幾個(gè)頁(yè)面呢?
第1個(gè):主頁(yè)面,顯示所有用戶的文章。
第2個(gè):登陸頁(yè)面,用戶在這里輸入用戶名和密碼
第3個(gè):顯示頁(yè)面,顯示某個(gè)用戶的文章
第4個(gè):編輯頁(yè)面,用戶在這里寫(xiě)新文章
(當(dāng)然,有一些功能也很重要,比如“修改”,比如“圖片”之類(lèi),慢慢來(lái)添加好不好?)
05、主頁(yè)面
現(xiàn)在我們來(lái)做主頁(yè)面,要能顯示數(shù)據(jù)庫(kù)中的數(shù)據(jù)。
我們直接來(lái)修改blog_1.py。
在import web這行代碼的下面添加:
import sqlite3
把print ‘index’這行代碼刪除,
添加:
con = sqlite3.connect("blog.db")
cur = con.cursor()
cur.execute(‘select * from user1′)
for row in cur:
print row
cur.close()
con.close()
把這個(gè)文件另存為:blog_2.py。并運(yùn)行之(記住要在命令提示符下運(yùn)行)。
然后我們打開(kāi)IE,輸入:http://127.0.0.1:8080/
我看到了:(u’2007-10-11′, u’1′, u’aaa’) (u’2008-01-19′, u’2′, u’bbbbb’) (u’1997-03-25′, u’3′, u’cc’)
你看到了沒(méi)有?
06、主頁(yè)面的第1次修改
其實(shí)blog_2.py是一個(gè)相當(dāng)不成熟的例子,我想你也能感覺(jué)出來(lái)。
因?yàn)閿?shù)據(jù)庫(kù)不是這樣用的,web.py是一個(gè)框架(Framework),
它提供了數(shù)據(jù)庫(kù)和模板的方便調(diào)用方法,這也是我們使用框架的原因。
現(xiàn)在讓我們來(lái)使用數(shù)據(jù)庫(kù)吧。
我們直接修改blog_1.py文件。
先在:web.run(urls, globals())這一行上面添加:
web.config.db_parameters = dict(dbn=’sqlite’, db=’blog.db’)
(這一行代碼是配置數(shù)據(jù)庫(kù)的,mysql的話還需要添加用戶名和密碼)
其中dbn表示數(shù)據(jù)庫(kù)的名稱,我們填入sqlite;
db表示具體數(shù)據(jù)庫(kù)的文件名稱,我們填入blog.db。
(注意:一定要加后綴名)
然后把print ‘index’這行代碼刪除,
添加新的代碼:
user1 = web.select("user1")
print user1[0].date
print len(list(user1))
(第1行是遍歷出整個(gè)user1表,第2行顯示user1表的第1個(gè)元素的number值,第3行顯示user1表的長(zhǎng)度)
(關(guān)于第3行看上去會(huì)有點(diǎn)奇怪,但是如果你試著用len(user1)這樣就會(huì)出錯(cuò),請(qǐng)?jiān)囍斫猓@就是“數(shù)據(jù)庫(kù)的方式”)
其中第1行可以改為user1 = web.query("select * from user1"),顯示出來(lái)的東西會(huì)是完全一樣的。
為什么呢?
因?yàn)楸举|(zhì)上是一樣的。但是web.query是用作查詢之用的,最好還是專職專用。
(詳細(xì)的還是要看C:\Python25\Lib\site-packages\web文件夾下面的db.py)
把這個(gè)文件另存為:blog_3.py。并運(yùn)行之。
在127.0.0.1:8080下面我們應(yīng)該能夠看到:“2007-10-11 2”
其中“2007-10-11”是user1[0].date的值;
“2”是“數(shù)據(jù)庫(kù)游標(biāo)之后部分的長(zhǎng)度”。
游標(biāo)是什么呢?即cursor(游標(biāo),指針),它指向數(shù)據(jù)庫(kù)的當(dāng)前位置。
接下來(lái),你可以試試把user1[0].number改成user1[1].number或者user[2].article,看看會(huì)顯示出來(lái)什么。
07、 主頁(yè)面的第2次修改
我們?cè)囍鴣?lái)顯示數(shù)據(jù)庫(kù)中所有的元素。
直接修改blog_3.py,其實(shí)主要就是修改index類(lèi)中的GET方法。代碼如下:
class index:
def GET(self):
user1 = web.select("user1")
user1_len = len(list(user1)) #數(shù)據(jù)庫(kù)長(zhǎng)度
user1_date = web.select("user1") #得到日期
user1_number = web.select("user1") #得到序號(hào)
user1_article = web.select("user1") #得到文章內(nèi)容
for i in range(0, user1_len):
print user1_date[i].date, \
user1_number[i].number, \
user1_article[i].article
另存為blog_4.py,并運(yùn)行之,應(yīng)該能看到:2007-10-11 1 aaa 2008-01-19 2 bbbbb 1997-03-25 3 cc
或者改為:
class index:
def GET(self):
user1 = web.select("user1")
user1_len = len(list(user1)) #數(shù)據(jù)庫(kù)長(zhǎng)度
user1_date = web.query("select date from user1") #得到日期
user1_number = web.query("select number from user1") #得到序號(hào)
user1_article = web.query("select article from user1") #得到文章內(nèi)容
for i in range(0, user1_len):
print user1_date[i].date, \
user1_number[i].number, \
user1_article[i].article
另存,運(yùn)行,得到的結(jié)果也和上面的一模一樣。
主要區(qū)別在于調(diào)用的方法不同,一個(gè)是web.select一個(gè)是web.query。
(我看到別人寫(xiě)的一個(gè)程序,好像都是用的web.query)
雖然這樣可以顯示,不過(guò)好丑!
怎么辦?用模板!
08、 用模板
(模板的英文是templates)
我們一步一步來(lái)看看模板怎么用。
首先,先創(chuàng)建一個(gè)目錄,名字就是templates。
然后,在這個(gè)目錄里面創(chuàng)建一個(gè)文件,名字是index.html。
那么往這個(gè)index.html上面寫(xiě)些什么呢?
$def with (user1_date)
<html>
<head>
<title>blog</title>
</head>
<body>
$user1_date[0].date
</body>
</html>
在blog_4.py上面直接修改,在import web的下一行加上:
render = web.template.render(‘templates/’)
然后另存為blog_5.py。
這主要是告訴程序模板文件的位置。
然后修改index類(lèi)的GET方法,原先的代碼統(tǒng)統(tǒng)刪掉,新代碼如下:
user1_date = web.query("select date from user1") #得到日期
print render.index(user1_date)
好了,現(xiàn)在保存,然后運(yùn)行blog_5.py吧。
我看到了:2007-10-11
你呢?
09 蛋炒飯
我放棄web.py有一段時(shí)間了。主要是因?yàn)樽约涸谧觯?
http://code.google.com/p/ssqpython/項(xiàng)目。
但是因?yàn)榭臻g的問(wèn)題,SSQPython項(xiàng)目也擱置了,
于是回頭來(lái)看web.py。
web.py官方發(fā)布版本還沒(méi)有更新,還是0.23(到2008-04-22為止)。
據(jù)說(shuō)在下一個(gè)版本0.3中,會(huì)更改render的顯示方式,把print改為return。
現(xiàn)在準(zhǔn)備重新把這個(gè)炒起來(lái)。
(注:其實(shí)我注意到了在code.google.com上面有類(lèi)似的項(xiàng)目)
我們先來(lái)重新完整的考慮一下整個(gè)blog系統(tǒng)的架構(gòu):
(注:如果你是從一開(kāi)始來(lái)看本文章的,也許到了這里你會(huì)有一點(diǎn)失望,
因?yàn)槲視?huì)重新來(lái)做,不過(guò)前面就當(dāng)作熱身了,好不好?)
- 登陸頁(yè)面(login.html) —- (這個(gè)頁(yè)面也同時(shí)作為注冊(cè)頁(yè)面,這樣好嗎?)
- 瀏覽頁(yè)面(blog.html) —- (這個(gè)頁(yè)面也是主頁(yè)面,即在不登陸的情況下顯示此頁(yè)面)
- 發(fā)表頁(yè)面(post.html)
以上3個(gè)頁(yè)面是用戶(user)的頁(yè)面。
我在這里省去了很多東西,比如:回復(fù)文章功能、修改文章功能、刪除文章功能等等。
而且將來(lái)可以添加用戶信息顯示及自定義功能。
我們?cè)賮?lái)考慮一下管理員(admin)的頁(yè)面:
- 登陸頁(yè)面(login.html) —- (管理員就不能有注冊(cè)頁(yè)面了,要在后臺(tái)進(jìn)行注冊(cè)及密碼修改等操作)
- 查看頁(yè)面(index.html) —- (瀏覽用戶的數(shù)據(jù),可刪除用戶、刪除文章……)
以上2個(gè)頁(yè)面也不是很完整,還有許多功能需要添加,但是目前我還沒(méi)有想到還有什么功能是必須的。
至于“登出”功能則會(huì)在每個(gè)頁(yè)面都顯示一個(gè)按鈕的方式來(lái)實(shí)現(xiàn)。
這些架構(gòu)的思考目前還不是很完善,我也是在一步一步摸索中……
(注:其實(shí)“標(biāo)簽”或者“類(lèi)別”的功能很重要,這個(gè)將來(lái)也要完善)
10 大排面(主瀏覽頁(yè)面–生成數(shù)據(jù)庫(kù))
我們現(xiàn)在假設(shè)數(shù)據(jù)庫(kù)中有很多很多數(shù)據(jù),我們現(xiàn)在只是要把它們顯示出來(lái)。
這個(gè)顯示頁(yè)面是主瀏覽頁(yè)面(index.html)。
首先我們來(lái)生成這樣的數(shù)據(jù)。
我們創(chuàng)建一個(gè)db.py文件。
文件內(nèi)容如下:
import sqlite3
con = sqlite3.connect(‘blog.db’)
cur = con.cursor()
cur.execute(‘create table article \
(articleID, articleTitle, articleContent, \
articleAuthor, articleTime)’)
insert_datas = (’1′, ‘title_1′, ‘content_1′, ‘user_1′, ’2008-01-01′)
cur.execute(‘insert into article \
(articleID, articleTitle, articleContent, \
articleAuthor, articleTime) values (?, ?, ?, ?, ?)’, \
insert_datas)
con.commit()
cur.close()
con.close()
運(yùn)行:python db.py
則會(huì)生成:blog.db文件
在這個(gè)數(shù)據(jù)庫(kù)中有1個(gè)表(table),
這個(gè)表有5個(gè)域(field)或者說(shuō)是5個(gè)列(column),
分別是:文章的ID號(hào)(這個(gè)會(huì)從1開(kāi)始排列到無(wú)窮大)
文章的標(biāo)題
文章的內(nèi)容
文章的作者
文章的時(shí)間(這里當(dāng)前記錄的文章的發(fā)表時(shí)間,將來(lái)會(huì)有另一個(gè)來(lái)記錄修改時(shí)間)
11 大肉面(主瀏覽頁(yè)面–主程序文件)
我們?cè)賱?chuàng)建一個(gè)blog.py,這個(gè)會(huì)是我們這個(gè)blog的主程序文件。
import web
render = web.template.render(‘templates/’)
urls = (
‘/’, ‘index’,
)
class index:
def GET(self):
datas = web.query("select * from article order by articleID desc")
print render.index(datas)
if __name__ == "__main__":
web.webapi.internalerror = web.debugerror
web.config.db_parameters = dict(dbn=’sqlite’, db=’blog.db’)
web.run(urls, globals(), web.reloader)
在這里我們定義了模板(template)的位置:templates文件夾。
并且定義了當(dāng)訪問(wèn)“/”的時(shí)候,調(diào)用index類(lèi)。
這表示我們?cè)L問(wèn)127.0.0.1的時(shí)候,會(huì)顯示index類(lèi)中的print內(nèi)容。
并且我們開(kāi)啟了debug,即:web.webapi.internalerror = web.debugerror
并設(shè)置數(shù)據(jù)庫(kù)為sqlite,訪問(wèn)文件為blog.db。
12 炸醬面(主瀏覽頁(yè)面–模板)
我們先創(chuàng)建一個(gè)文件夾:templates。
在這個(gè)文件夾下面創(chuàng)建一個(gè)index.html文件,這個(gè)文件就是我們用到的模板。
文件內(nèi)容如下:
$def with (datas)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>blog</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<div id="wrapper">
<div id="logo">
<p>Blog</p>
</div>
<div id="nav">
</div>
<div id="article">
$for data in datas:
<div id="title">
<p>$data.articleTitle</h3>
</div>
<div id="time">
<p>$data.articleTime</p>
</div>
<div id="content">
<p>$data.articleContent</p>
</div>
<div id="author">
<p>Post by $data.articleAuthor</p>
</div>
</div>
</div>
<div id="copyright">
<p>Copyright © 2008 otherrrr. All rights reserved.</p>
</div>
</div>
</body>
</html>
其中:
<!DOCTYPE …….>是定義HTML的文件格式
<head>文件頭
<title>文件標(biāo)題
<meta ……>文檔的其他信息
<body>主體
<div id="">之類(lèi)的東西,CSS+DIV。
目前我們還沒(méi)有用上CSS,先定義一下,將來(lái)一定會(huì)用上的。
$def with (datas)定義了傳遞過(guò)來(lái)的變量,
這個(gè)與blog.py中的print render.index(datas)
相對(duì)應(yīng)。
$for data in datas:是想循環(huán)顯示所有數(shù)據(jù)。
datas是一個(gè)storage格式的數(shù)據(jù),類(lèi)似與dict(字典),
所以調(diào)用其中的值時(shí)可以用[],例如data['articleTitle']
但是用“.”無(wú)疑更為方便!
13 鹵肉飯(主瀏覽頁(yè)面–好了)
好了,現(xiàn)在我們運(yùn)行一下吧:python blog.py
(這個(gè)要在命令行下運(yùn)行)
顯示:http://0.0.0.0:8080/
在瀏覽器中訪問(wèn)網(wǎng)址:http://127.0.0.1:8080/
(請(qǐng)把這個(gè)網(wǎng)址添加到瀏覽器的收藏夾中,因?yàn)樵诤竺鏁?huì)多次用到)
(而且我建議用Firefox,因?yàn)橛行┎寮杏X(jué)挺不錯(cuò)的,F(xiàn)irebug/YSlow)
可以看到:
title_1 – user_1
content_1
2008-01-01
因?yàn)楝F(xiàn)在只有一組數(shù)據(jù),所以只顯示了一組數(shù)據(jù)。
順便說(shuō)一下:如果你想修改端口,可以這樣:python blog.py 80
這樣就可以瀏覽:http://127.0.0.1/了。
14 雞腿飯(主瀏覽頁(yè)面–多個(gè)文章同時(shí)顯示)
現(xiàn)在我們開(kāi)始修改了,你最好把剛才那些文件另存為一下,
以免修改過(guò)程中出現(xiàn)“天災(zāi)人禍”。
我們首先修改db.py,新的代碼如下:
import sqlite3
con = sqlite3.connect(‘blog.db’)
cur = con.cursor()
cur.execute(‘create table article \
(articleID, articleTitle, articleContent, \
articleAuthor, articleTime)’)
insert_datas = (’1′, ‘title_1′, ‘content_1′, ‘user_1′, ’2008-01-01′)
cur.execute(‘insert into article \
(articleID, articleTitle, articleContent, \
articleAuthor, articleTime) values (?, ?, ?, ?, ?)’, \
insert_datas)
insert_datas = (’2′, ‘title_2′, ‘content_2′, ‘user_2′, ’2008-02-02′)
cur.execute(‘insert into article \
(articleID, articleTitle, articleContent, \
articleAuthor, articleTime) values (?, ?, ?, ?, ?)’, \
insert_datas)
con.commit()
cur.close()
con.close()
其實(shí)主要是又添加了一組數(shù)據(jù)。
刪除目錄下的blog.db,然后運(yùn)行:python db.py
重新啟動(dòng):python blog.py,在瀏覽器下可以看到:
title_2 – user_2
content_2
2008-02-02
title_1 – user_1
content_1
2008-01-01
是的,你很聰明的發(fā)現(xiàn)了,這是倒序的,也就是最后插入的數(shù)據(jù)在最上面顯示。
這時(shí)我故意的:注意blog.py中的代碼:
datas = web.query("select * from article order by articleID desc")
注意到了desc了嗎?
desc表示倒序。
你可以試著刪除desc來(lái)看看顯示效果。
提示:當(dāng)你修改blog.py的時(shí)候,并不用關(guān)閉web server,
修改完成后也不用重啟,可直接刷新頁(yè)面瀏覽。
這是因?yàn)槲覀冊(cè)赽log.py中的最后一行加了: web.reloader
15 茶蛋(網(wǎng)頁(yè)鏈接CSS)
網(wǎng)頁(yè)中插入CSS的方式有兩種(我就知道兩種,具體幾種方式不確定)
一種是連接文件:
我們來(lái)修改一下index.html:
在</head>上面插入一行:
<link rel="stylesheet" type="text/css" href="/static/style.css">
提示:當(dāng)修改template文件夾中的文件之后,必須重啟才能看到效果。
我們重啟一下,看看瀏覽器中顯示什么。
什么也沒(méi)發(fā)生變化!
但是在命令行下,我們可以看到:
… /static/style.css" – 404 File not found
我們先創(chuàng)建一個(gè)文件夾:static,這個(gè)名字是web.py默認(rèn)的放置靜態(tài)文件的目錄名。
然后創(chuàng)建一個(gè)style.css,可以用記事本或者之類(lèi)的東西創(chuàng)建。
(我用gVim,對(duì)于vim我有這樣的感受:它確實(shí)提高了我的效率,但是也讓我的手——
變得更累了)
文件內(nèi)容如下:
*******
(注:在百度的blog中填寫(xiě)css代碼,會(huì)給顯示出來(lái),暫時(shí)無(wú)法給出CSS的代碼)
然后刷新瀏覽器,感覺(jué)非常慢,
但是最終還是顯示出來(lái)了。
字體、顏色、位置有了些變化,是不是?
詳細(xì)的CSS介紹我就不說(shuō)了,不過(guò)CSS對(duì)于網(wǎng)站的美觀真的很重要。
16 咸鴨蛋(網(wǎng)頁(yè)內(nèi)置CSS)
我們也可以把CSS放到HTML中。
現(xiàn)在我們重新修改index.html,刪掉<link ……這一行。
在</head>上面加入如下文字:
<style type="text/css">
*******
</style>
(注:在百度的blog中填寫(xiě)css代碼,會(huì)給顯示出來(lái),暫時(shí)無(wú)法給出CSS的代碼)
其中的設(shè)置和style.css一模一樣。
重啟服務(wù)器,刷新瀏覽器。是不是快很多了?
據(jù)說(shuō)用lighttpd或apache作為web server(服務(wù)器),
對(duì)于像CSS文件這樣的靜態(tài)文件的讀取會(huì)有很大的提高。
這個(gè)我正在嘗試中。
17 軟炸里脊(用戶發(fā)表文章代碼)
用戶發(fā)表文章,就是向數(shù)據(jù)庫(kù)中添加信息。
首先修改blog.py
修改urls,代碼如下:
urls = (
‘/’, ‘index’,
‘/add’, ‘add’,
)
即定義網(wǎng)址后面是“/add”的會(huì)調(diào)用add類(lèi)。
然后我們來(lái)寫(xiě)add類(lèi)。
class add:
def GET(self):
print render.add()
def POST(self):
i = web.input()
t = time.localtime(time.time())
st = time.strftime("%Y-%m-%d", t)
datas = list(web.query("select * from article order by articleID desc"))
n = web.insert(‘article’,
articleID=str(len(datas)+1), \
articleTitle=i.post_title, \
articleContent=i.post_content, \
articleAuthor=’user_3′, \
articleTime=st)
web.seeother(‘/’)
GET中定義顯示add.html這個(gè)模板。
POST中定義來(lái)提交后的處理。
i = web.input()
得到網(wǎng)頁(yè)中提交的數(shù)據(jù)。
time部分是處理日期的格式。
注意:需要在blog.py最前面加上import time。
datas = list(…)
這部分是算一下當(dāng)前的ID會(huì)是多少。
為什么len(datas)+1要加str呢?
因?yàn)椴患觭tr的話,排序會(huì)有問(wèn)題。
我個(gè)人認(rèn)為sqlite太過(guò)于隨便,不需要初始定義數(shù)據(jù)的類(lèi)型,
但是到后面才發(fā)現(xiàn),其實(shí)預(yù)先定義還是有好處的。
這里面我們的用戶暫時(shí)先默認(rèn)為“user_3”,將來(lái)會(huì)改的。
web.seeother(‘/’)
表示我們會(huì)跳轉(zhuǎn)到“/”網(wǎng)址,也就是主頁(yè)面。
這部分將來(lái)也需要改,我初步的想法是跳到“/blog”頁(yè)面。
簡(jiǎn)單說(shuō)一下web.seeother()和web.redirect()的區(qū)別。
redirect()無(wú)法后退,后退時(shí)會(huì)提示:是否需要重新提交數(shù)據(jù)。
官方說(shuō)明里面說(shuō):當(dāng)徹底跳轉(zhuǎn)的時(shí)候最好用redirect()。
(注:感覺(jué)web.py的官方文檔真的很少,而且有一部分是針對(duì)0.3版本的,
但是主頁(yè)能下載的卻是0.23版本的)
(注:web2py不知道大家用過(guò)沒(méi)有,在郵件列表中感覺(jué)其作者“非常”熱情,
如果一個(gè)禮拜當(dāng)中提問(wèn)的人少,他都會(huì)說(shuō)“太安靜了”,呵呵)
18 糖醋里脊(用戶發(fā)表文章頁(yè)面)
我們?cè)趖emplates目錄下創(chuàng)建一個(gè)add.html。
我們需要:
一個(gè)輸入文章標(biāo)題的文本框、
一個(gè)輸入文章內(nèi)容的文本框、
一個(gè)提交按鈕。
(我們現(xiàn)在沒(méi)有考慮用戶登陸的情況,
在實(shí)際情況下,如果用戶未登陸,
那么應(yīng)該提示用戶登陸,并引導(dǎo)
用戶到登陸頁(yè)面)
代碼如下(我隱去了CSS部分的代碼):
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>post</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<div id="wrapper">
<div id="logo">
<p>Blog</p>
</div>
<div id="post">
<form action="/add" method="post">
<label for="post_title">Title</label><br />
<textarea id="post_title" name="post_title" cols="60" rows="1"></textarea><br />
<label for="post_content">Content</label><br />
<textarea id="post_content" name="post_content" cols="80" rows="10"></textarea><br />
<input type="submit" name="post_submit" value="Post it" />
</form>
</div>
<div id="copyright">
<p>Copyright © 2008 otherrrr. All rights reserved.</p>
</div>
</div>
</body>
</html>
其中<form>定義了一個(gè)提交表單。
表單中有兩個(gè)文本域(textarea),一個(gè)用來(lái)輸入標(biāo)題,一個(gè)用來(lái)輸入內(nèi)容。
并定義了一個(gè)提交按鈕。
也許你會(huì)問(wèn)<br />是怎么回事?和<br>有什么區(qū)別。
都是換行的意思。
但是從符合w3c的角度來(lái)說(shuō)<br />更規(guī)范。
(就是說(shuō)沒(méi)有結(jié)束符的標(biāo)簽最好自己本身帶一個(gè)結(jié)束符“/”,
同理還有input標(biāo)簽)
那么w3c是什么?一個(gè)網(wǎng)頁(yè)規(guī)范組織。
19 清蒸里脊(發(fā)表文章測(cè)試)
在瀏覽器中訪問(wèn):http://127.0.0.1:8080/add
如果無(wú)法訪問(wèn),請(qǐng)確認(rèn)你的web服務(wù)器已經(jīng)開(kāi)啟了。
輸入一點(diǎn)東西吧,然后點(diǎn)擊“Post it”按鈕,
看看效果。
再試一次,多輸入點(diǎn)文字,看看有什么不同。
我發(fā)現(xiàn)一個(gè)問(wèn)題,如果輸入多行數(shù)據(jù),但是顯示的時(shí)候卻是一行。
只是數(shù)據(jù)之間加了空格。
如果要保證顯示完全正確,是不是需要將“\n”改為“<p>”。
20 糖醋魚(yú)(用戶登陸代碼)
修改blog.py,在urls中添加login,修改后代碼如下:
urls = (
‘/’, ‘index’,
‘/add’, ‘add’,
‘/login’, ‘login’,
)
并創(chuàng)建一個(gè)login類(lèi),代碼如下:
class login:
def GET(self):
print render.login()
def POST(self):
i = web.input()
web.setcookie(‘id’, ’1′)
web.setcookie(‘username’, i.post_username)
web.seeother(‘/blog’)
在GET()中我們定義了顯示login模板。
在POST()中我們定義了接收到輸入后,跳轉(zhuǎn)到網(wǎng)址“/blog”。
注意看,這里我用到了cookie。
cookie可以記錄用戶訪問(wèn)網(wǎng)站的一些信息。
如果我們不關(guān)掉瀏覽器,那么這個(gè)cookie會(huì)一直在。
(因此我們將來(lái)一定要做退出)
其中需要設(shè)置兩個(gè)值,id和username。
在這里id我是未做完的狀態(tài),固定為“1”。
正常情況下,應(yīng)該判斷用戶的帳戶在數(shù)據(jù)庫(kù)中有沒(méi)有,以及密碼是否正確。
如帳戶和密碼都正確就從數(shù)據(jù)庫(kù)中返回出一個(gè)id號(hào)。
username則是輸入的值。
(在登陸頁(yè)面,其實(shí)最好用一些JavaScript來(lái)做判斷。
如:用戶名或密碼是否為空等等)
21 水煮魚(yú)(用戶登陸頁(yè)面)
在撞見(jiàn)用戶登陸頁(yè)面之前,我們先從首頁(yè)加個(gè)鏈接。
修改index.html。
代碼中添加對(duì)login頁(yè)面的鏈接:
<div id="nav">
<a href="/login">Log in</a>
</div>
并添加對(duì)應(yīng)CSS設(shè)置部分。
然后在templates文件夾下創(chuàng)建login.html文件。
文件中的內(nèi)容如下:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Log in</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<div id="wrapper">
<div id="logo">
<p>Blog</p>
</div>
<div id="post">
<form action="/login" method="post">
<label for="post_username">Username</label><br />
<input id="post_username" name="post_username"><br />
<label for="post_password">Password</label><br />
<input id="post_password" name="post_password" type="password"><br />
<input type="submit" name="post_login" value="Login" />
</form>
</div>
<div id="copyright">
<p>Copyright © 2008 otherrrr. All rights reserved.</p>
</div>
</div>
</body>
</html>
注:文件省去了CSS設(shè)置部分。
我們定義了一個(gè)表單(form),用來(lái)提交信息。
然后有兩個(gè)輸入框(input),一個(gè)用來(lái)輸入用戶,一個(gè)用來(lái)輸入密碼。
還有一個(gè)提交(submit)按鈕,用來(lái)登陸。
密碼框的類(lèi)型(type)一定要指定為“password”。
不然你輸入密碼旁邊的眼神好的小子就能看見(jiàn)了。
22 家燜黃花魚(yú)(跳轉(zhuǎn)到blog頁(yè)面)
首先我們還是要該blog.py
urls里面加上:’/blog’, ‘blog’,
(我覺(jué)得你現(xiàn)在應(yīng)該知道這個(gè)怎么加了)
然后我們定義blog類(lèi):
class blog:
def GET(self):
session = web.cookies()
datas = web.query("SELECT * FROM article where articleAuthor=$session.username", vars=locals())
print render.blog(datas, session)
我們這里得到了cookies()。
并且我們從數(shù)據(jù)庫(kù)中查找作者名為登陸用戶名的所有文章。
接下來(lái),是的,我們需要?jiǎng)?chuàng)建blog模板了。
代碼如下(沒(méi)有CSS版本的):
$def with (datas, session)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>blog</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<div id="wrapper">
<div id="logo">
<p>Blog</p>
</div>
<div id="nav">
<ul>
<li><a href="/logout">Logout</a></li>
<li><a href="/add">Add</a></li>
<li><p>$session.username</p><li>
</ul>
</div>
<div id="article">
$for data in datas:
<div id="title">
<p>$data.articleTitle</h3>
</div>
<div id="time">
<p>$data.articleTime</p>
</div>
<div id="content">
<p>$data.articleContent</p>
</div>
<div id="author">
<p>Post by $data.articleAuthor</p>
</div>
</div>
<div id="copyright">
<p>Copyright © 2008 otherrrr. All rights reserved.</p>
</div>
</div>
</div>
</body>
</html>
是的,這個(gè)和index.html非常相似。我就是從index.html上面改的。
主要不同的是這里:
<div id="nav">
<ul>
<li><a href="/logout">Logout</a></li>
<li><a href="/add">Add</a></li>
<li><p>$session.username</p><li>
</ul>
</div>
我加了2個(gè)鏈接,一個(gè)是Logout(登陸出),一個(gè)是Add(添加文章)。
并添加顯示了登陸進(jìn)來(lái)的用戶名。
注意最前面的部分:
$def with (datas, session)
是的,我們繼承(獲取?)了session變量。
不然我們沒(méi)辦法顯示用戶名,對(duì)不對(duì)?
23 炸刀魚(yú)(測(cè)試登陸一下下)
首先在index.html里面加一個(gè)鏈接:
<div id="nav">
<a href="/login">Log in</a>
</div>
主要是為了鏈接到login(登陸)頁(yè)面。
我們先重啟一下Web服務(wù)器:python blog.py
然后,在瀏覽器中訪問(wèn)http://127.0.0.1/
這會(huì)讓我們看到所有用戶的文章。
然后我們點(diǎn)擊Login鏈接,跳轉(zhuǎn)到http://127.0.0.1/login
這個(gè)就是登陸頁(yè)面。
輸入用戶名:user_2
輸入密碼:*****(隨便輸什么都行,因?yàn)槲覀儾](méi)有驗(yàn)證用戶和密碼的有效性)
然后點(diǎn)擊Login按鈕。
唰一下,跳轉(zhuǎn)到http://127.0.0.1/blog。
在這里,我們只看見(jiàn)了user_2發(fā)布的文章。
你可以重復(fù)試試登陸user_1或user_3。
(我也不知道自己為什么會(huì)用菜名作為小節(jié)名,大概是因?yàn)橹形缈偝圆缓玫木壒拾桑?/p>
24 火爆腰花(CSS的新處理方法)
把CSS放到網(wǎng)頁(yè)中無(wú)疑是非常不爽的。
我們來(lái)改一下下。
Blog.py中修改urls:
‘/styles.css’, ‘style’,
然后添加新的類(lèi)(即處理方法):
class style:
def GET(self):
web.header("Content-Type","text/css; charset=utf-8")
print open(‘static/styles.css’).read()
網(wǎng)頁(yè)中寫(xiě)法如下:
<link rel="stylesheet" type="text/css" href="styles.css" />
然后只要將styles.css放在templates目錄下就可以了。
25 黃瓜蜇皮(修改add類(lèi))
我們添加一項(xiàng),當(dāng)?shù)顷懼髸?huì)將用戶名添加到數(shù)據(jù)庫(kù)中。
session = web.cookies()
(好像反復(fù)的讀取好像這個(gè)不太對(duì),不過(guò)我現(xiàn)在還不會(huì)在web.py內(nèi)部傳遞變量)
數(shù)據(jù)存儲(chǔ):sql加上x(chóng)ml,sql記錄正文數(shù)據(jù),xml記錄不常變動(dòng)的數(shù)據(jù)
(最后更新時(shí)間:2008-05-06下午)
(otherrrr@gmail.com)