自定義公告板

公告板,我理解的是不是門崗大爺旁邊的那個,通知我們最近需要我們注意的事情,我想除了檢查衛生沒別的了,而且好久也不見更新,還有一個就是電子公告板,流水字那個,就是很多二極管組成的數碼管來顯示字的那種(而且需要流動的),當然這個項目不是這個,公告板就是顯示信息來通知別人的,那麼這些信息是存儲在那的呢?進入公告標題,裏面應該是其內容或者還有一些其他的信息,這篇是把信息存在數據庫裏。

先看看數據庫中建的一個表吧:

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頁面。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章