公告板,我理解的是不是門崗大爺旁邊的那個,通知我們最近需要我們注意的事情,我想除了檢查衛生沒別的了,而且好久也不見更新,還有一個就是電子公告板,流水字那個,就是很多二極管組成的數碼管來顯示字的那種(而且需要流動的),當然這個項目不是這個,公告板就是顯示信息來通知別人的,那麼這些信息是存儲在那的呢?進入公告標題,裏面應該是其內容或者還有一些其他的信息,這篇是把信息存在數據庫裏。
先看看數據庫中建的一個表吧:
create table messages(
id int not null auto_increment,
subject varchar(100) not null,
sender varchar(15) not null,
reply_to int,
text mediumtext not null,
primary key(id));
如代碼所示,只是建了 id ,subject,sender,reply_to,text,等5個字段和各自的類型及最大字符串長度。其中主鍵是id.
作爲一個公告板,一定能顯示信息和編輯信息吧。
先看看公告板的主頁代碼,所有通知的信息都應該在主頁顯示,不然該去哪看。
print 'Content-type:text/html\n'
print
#import cgitb:cgitb.enable()
import MySQLdb
conn = MySQLdb.connect(db='hu',user='root')
curs = conn.cursor()
print '''
<html>
<head>
<title>The hu yiyang</title>
</head>
<body>
<h1>The hu yiyang </h1>
'''
curs.execute('SELECT * FROM messages')
rows = curs.fetchall()
toplevel = []
children = {}
for row in rows:
parent_id = row[3]
if parent_id is None:
toplevel.append(row)
else:
children.setdefault(parent_id,[]).append(row)
def format(row):
print '<p><a href="view.cgi?id=%i">%s<a>' %
(row[0],row[1])
try:
kids = children[row[0]]
except KeyError:
pass
else:
print '<blockquote>'
for kid in kids:
format(kid)
print '</blockquote>'
print '<p>'
for row in toplevel:
format(row)
print '''
</p>
<hr/>
<p><a href="edit.cgi">Post Messages</a></p>
</body>
</html>
'''
剛開始與數據庫進行連接,‘hu’是數據庫名,‘root’是用戶名。conn.cursor()是用來獲取連接數據庫的浮標,用於使用sql語句,下面就是打印一些信息,curs.execute()就是執行裏面的sql語句,檢索messages表中的所有字段信息,下面的curs.fetchall()就是把檢索的信息按序列輸出顯示,下面這個for是處理有沒有回覆的消息,如果該主題沒有人回覆就把該行記錄存儲 在toplevel列表中,否則就吧該行記錄記錄到chilren字典中,其中setdefault函數的意思是如果parent_id有值(不是None),也就是有人回覆信息,就把該行記錄存儲在children字典中(當然可以很多人回覆消息,所以採用字典來存儲),最終就是說沒人回覆的主題放在toplevel中,有人回覆的放在children中。接着是format函數,主要進行對每一條記錄顯示的問題,
print '<p><a href="view.cgi?id=%i">%s<a>' % (row[0],row[1])的意思就是隻要你點擊某個主題,就會連接到其對應的內容裏,然後又是捕捉異常的了,如果children[row['0']]有值,也就是說有回覆信息,就會在該主題裏顯示出該回覆信息,否則會引發一個KeyError異常,不過這個異常的執行是pass.,對應沒人回覆的信息也會執行一次format來鏈接顯示這個主題。最後還有一個鏈接是Post messages,用於鏈接到編輯頁面,edit.cgi.
下面看edit.cgi代碼:
print 'Content-type: text/html\n'
#import cgitb: cgitb.enable()
import MySQLdb
conn = MySQLdb.connect(db='hu',user='root')
curs = conn.cursor()
import cgi,sys
form = cgi.FieldStorage()
reply_to = form.getvalue('reply_to')
print """
<html>
<head>
<title>Compose Messages</title>
</head>
<body>
<h1>Compose Messages</h1>
<form action='/cgi-bin/save.cgi' method='POST'>
"""
subject = ''
if reply_to is not None:
print '<input type="hidden" name="reply_to"
value="%s"/>'% reply_to
curs.execute('SELECT subject FROM messages WHERE
id=%s'% reply_to)
subject = curs.fetchone()[0]
if not subject.startswith('Re: '):
subject = 'Re: '+subject
print '''
<b>Subject:</b><br/>
<input type='text' size='40' name='subject'
value='%s' /><br/>
<b>Sender:</b><br />
<input type='text' size='40' name='sender' /><br/>
<b>Message:</b><br/>
<textarea name='text' cols='40'
rows='20'></textarea><br/>
<input type='submit' value='Save'/>
</form>
<hr/>
<a href='main.cgi'>back to the main page</a>
</body>
</html>
''' % subject
剛開始都一樣,都是鏈接存儲信息的數據庫,並且獲取連接數據庫的遊標,以用於使用sql語句。cgi.FieldStorage()在上個項目就有,是用來獲取上個頁面提交過來的信息(也就是main.cgi),先獲取字段名爲‘reply_to’的信息(他中存儲的是被回覆那個主題的ID),存儲到reply_to中,下面也是一個打印本頁標題的html, <form action='/cgi-bin/save.cgi' method='POST'>就是一個提交表單,要跳轉的頁面,action的值可以是本站點的url地址,也可以是其他站點的。如果有回覆的信息,就把名爲‘reply_to’,值爲‘
被回覆主題的ID ’的信息隱藏起來(編輯該主題的時候並不需要看該主題的回覆情況吧),接着是執行一條sql語句,意思是檢索 messages表中id爲reply_to的值的主題(就是查找被回覆的那個主題),如果主題的開始不爲‘Re : ’,則在回覆的時候,主題前面自動加上‘Re:’,最後就是html了,各自的標題及文本框,還有個提交按鈕‘Save’,用於跳轉到save.cgi,還有個鏈接 back to the main page,用以回到主頁。
下面看 save.cgi代碼:
print 'Content-type:text/html\n'
import cgitb;cgitb.enable()
def quote(string):
if string:
return string.replace("'","\\'")
else:
return string
import MySQLdb
conn = MySQLdb.connect(db='hu',user='root')
curs = conn.cursor()
import cgi, sys
form = cgi.FieldStorage()
sender = quote(form.getvalue('sender'))
subject = quote(form.getvalue('subject'))
text = quote(form.getvalue('text'))
reply_to = form.getvalue('reply_to')
if not (sender and subject and text):
print 'Please supply sender,subject,text'
sys.exit()
if reply_to is not None:
query = """
INSERT INTO messages
(reply_to,sender,subject,text)
VALUES(%d,'%s','%s','%s')""" % (int
(reply_to),sender,subject,text)
else:
query = """
INSERT INTO messages(sender,subject,text)
VALUES('%s','%s','%s')""" %
(sender,subject,text)
curs.execute(query)
conn.commit()
print '''
<html>
<head>
<title>Messages Saved</title>
</head>
<body>
<h1>Messages Saved</h1>
<hr/>
<a href='main.cgi'>Back to the main page</a>
</body>
</html>s
'''
剛開始就定義一個quote函數,如果字符串存在,就把‘ ‘ ’換成’ \' ‘,否則返回本身。下面都是把獲取到的值經過quote函數再賦給一個變量,而字段’reply_to‘就不需要,因爲他是個整型,就直接獲取了。下面意思是如果sender ,subject,text中有一個不存在(必須三個都存在纔可以不執行下面的打印),就會打印需要你輸入的信息,然後退出代碼。
如果回覆不爲空,就往messages表中插入一條回覆信息的記錄,包括(reply_to,sender,subject,text),如果回覆爲空,就往messages表中插入一條不含有reply_to的記錄,就是該條信息沒人回覆。commit()是把提交給數據庫的信息更新。最後還是HTML,一個鏈接,back to the main page.
最後是 view.cgi:
print 'Content-type:text/html\n'
#import cgitb:cgitb.enable()
import MySQLdb
conn = MySQLdb.connect(db='hu',user='root')
curs = conn.cursor()
import cgi,sys
form = cgi.FieldStorage()
id = form.getvalue('id')
print """
<html>
<head>
<title>View Messages</title>
</head>
<body>
<h1>View Messages</h1>
"""
try:
id = int(id)
except:
print 'Invalid messages ID'
sys.exit()
curs.execute('SELECT * FROM messages WHERE id=%d'%id )
rows = curs.fetchall()
if not rows:
print 'Unknown message ID'
sys.exit()
row = rows[0]
print '''
<p><b>Subject:</b> %s<br/>
<b>Sender:</b>%s<br/>
<pre>%s</pre>
</p>
<hr/>
<a href='main.cgi'>Back to the main page</a>
|<a href="edit.cgi?reply_to=%s">Reply</a>
</body>
</html>
''' % (row[1],row[2],row[4],row[0])
前面一樣,不過這個獲取上頁傳來的id的值,主要是用於顯示id爲某個值的那條記錄,一個捕捉id類型的異常。然後是一個數據庫查詢,查找傳過來的那個id的所有記錄,如果沒有記錄則打印未知的id,最後是一個html,比較不同的是這個裏面加了個、Reply的鏈接,用於回覆信息跳轉到edit.cgi頁面。