7. Python脚本学习实战笔记七 电子公告板
7. Python脚本学习实战笔记七 电子公告板
本篇名言:“不管生活如何变故,道路如何曲折,你千万别掉队,因为希望和梦想就在前面。”
1. 需求
如何创建通过网络发布和回复信息的简单系统.系统内有自己的一个作为论坛的机制。
2. 工具和准备
除了CGI工具外,
还需要一个SQL数据库,这里使用PostgreSQL数据库。
下载地址如下:
http://www.enterprisedb.com/products-services-training/pgdownload#windows
双击安装即可。
此外,还需要一个与PostgrelSQL数据库通信的API模块,使用psycopg即可。
下载链接如下
http://www.stickpeople.com/projects/python/win-psycopg/
注意Python版本号和 postgrelSQL的版本号。
双击安装后,进行导入 import psycopg2 即可判断是否正常。
2.1 创建数据库
数据库的结构和所要解决的问题联系的很紧密。
打开PostgrelSQL命令行模式如下图1:
#create database bbs;
#\c bbs;
#CREATE TABLE messages (
id SERIAL PRIMARY KEY,
subject TEXT NOT NULL,
sender TEXT NOT NULL,
reply_to INTEGER REFERENCESmessages,
text TEXT NOT NULL
);
#\d
显示如下:
关联列表
架构模式 | 名称 | 型别 | 拥有者
----------+-----------------+--------+----------
public | messages | 资料表 |postgres
public | messages_id_seq | 序列数 | postgres
(2 行记录)
拥有5个字段,
Id用于标识唯一的消息
subject包括消息主体的字符串
Sender:包括发送者名字、EMAIL地址或者其他信息的字符串
Reploy_to :如果消息是回复其他消息的、那么这个字段就包括那个消息的ID
Text: 包括消息内容的字符串。
3. 初次实现
先进行一个简单那的测试:
>>> import psycopg2
>>>conn=psycopg2.connect('user=postgres password=huawei dbname=bbs')
>>> curs=conn.cursor()
>>> curs.execute('select * frommessages')
>>> curs.fetchall()
[]
所有信息为空,所以没有得到什么。
对于每个消息来说,获取reply_to字段,如果是None(不是回复),那么将这条消息添加到顶级消息的李彪。否则将其添加到children[parent_id]自列表中。
为顶级消息调用format函数。Format函数打印消息的主题。而且如果消息有任何回复的话,会打开一个blockquote元素,对于每一个回复调用format函数(递归),然后结束blockquote元素。
正式初次实现代码如下:
#!D:\python27\python.exe
print'Content-type: text/html\n'
importcgitb; cgitb.enable()
importpsycopg2
conn = psycopg2.connect('dbname=bbs user=postgres password=huawei')
curs = conn.cursor()
print"""
<html>
<head>
<title>The FooBar BulletinBoard</title>
</head>
<body>
<h1>The FooBar BulletinBoard</h1>
"""
curs.execute('SELECT * FROM messages')
rows = curs.fetchall()
toplevel = []
children = {}
forrow in rows:
parent_id = row['reply_to']
if parent_id isNone:
toplevel.append(row)
else:
children.setdefault(parent_id,[]).append(row)
def format(row):
print row['subject']
try: kids =children[row['id']]
except KeyError: pass
else:
print'<blockquote>'
for kid in kids:
format(kid)
print'</blockquote>'
print'<p>'
forrow in toplevel:
format(row)
print"""
</p>
</body>
</html>
"""
如果数据库为空,那么现实就是空白了,这个没关系,只要不报警即可。
4. 再次实现
架构WEB程序使用类似CGI技术,最简单的方法是对用户执行的每个操作写一个脚本。
对于本系统需要如下脚本:
Main.cgi,显示所有消息的主题
View.cgi,显示一篇文章
Edit.cgi,编辑的表单中显示一篇文章,页面的提交Sumbit按钮链接到能实现保存功能的脚本。
Save.cig,获取edit.cgi文章的信息,并将其作为新行插入到数据库的表中进行保存。
4.1 Main脚本
加入链接,每个主题都会连接到给定的消息(view.cgi).在页面的下方还会添加一个允许用户发布新消息的链接,连接到edit.cgi.
具体如下:
#!D:\python27\python.exe
print'Content-type: text/html\n'
importcgitb; cgitb.enable()
importpsycopg2
conn = psycopg2.connect('dbname=bbs user=postgres password=huawei')
curs = conn.cursor()
print"""
<html>
<head>
<title>The FooBar BulletinBoard</title>
</head>
<body>
<h1>The FooBar Bulletin Board</h1>
"""
curs.execute('SELECT * FROM messages')
rows = curs.fetchall()
toplevel = []
children = {}
forrow in rows:
parent_id = row[3]
if parent_id isNone:
toplevel.append(row)
else:
children.setdefault(parent_id,[]).append(row)
def format(row):
print'<p><a href="view.cgi?id=%i">%s</a></p>' % (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>'
forrow in toplevel:
format(row)
print"""
</p>
<hr />
<p><a href="edit.cgi">Postmessage</a></p>
</body>
</html>
"""
执行如下图2:
点击Post message跳转到edit.cgi.
编辑后出现如下3
4.2 View脚本
代码如下:
#!D:\python27\python.exe
print 'Content-type: text/html\n'
import cgitb; cgitb.enable()
import psycopg2
conn = psycopg2.connect('dbname=bbs user=postgres password=huawei')
curs = conn.cursor()
import cgi, sys
form = cgi.FieldStorage()
id = form.getvalue('id')
print """
<html>
<head>
<title>ViewMessage</title>
</head>
<body>
<h1>ViewMessage</h1>
"""
try: id = int(id)
except:
print 'Invalid message ID'
sys.exit()
curs.execute('SELECT * FROM messages WHERE id = %i' % 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 />
<ahref='main.cgi'>Back to the main page</a>
| <ahref="edit.cgi?reply_to=%i">Reply</a>
</body>
</html>
""" % (row[1],row[2],row[4],row[0])
4.3 Edit脚本
Edit.cgi 用于编辑新消息,也用于编辑回复。
如果提供了reply_to参数,那么会被保存在编辑表单的一个隐藏输入(hidden input)中。除此之外,主题会默认设定为“Re:parentsubject” ,除非主题已经以”Re:”
代码如下:
#!/usr/bin/python
print 'Content-type:text/html\n'
import cgitb; cgitb.enable()
import psycopg
conn =psycopg.connect('dbname=foo user=bar')
curs = conn.cursor()
import cgi, sys
form = cgi.FieldStorage()
reply_to =form.getvalue('reply_to')
print """
<html>
<head>
<title>Compose Message</title>
</head>
<body>
<h1>Compose Message</h1>
<form action='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 messagesWHERE 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 mainpage</a>'
</body>
</html>
""" % subject
被调用后执行如下 图4:
点击back to the main page调用main.cgi.
点击save调用save.cgi.
如下图5
4.4 Save脚本
脚本如下:
#!D:\python27\python.exe
print'Content-type: text/html\n'
importcgitb; cgitb.enable()
def quote(string):
if string:
return string.replace("'", "\\'")
else:
return string
importpsycopg
conn = psycopg.connect('dbname=bbs user=postgres password=huawei')
curs = conn.cursor()
importcgi, 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')
ifnot (sender and subject and text):
print'Please supply sender, subject, and text'
sys.exit()
ifreply_to isnotNone:
query = """
INSERT INTO messages(reply_to, sender,subject, text)
VALUES(%i, '%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>Message Saved</title>
</head>
<body>
<h1>Message Saved</h1>
<hr />
<a href='main.cgi'>Back to themain page</a>
</body>
</html>s
"""
在Edit.cgi中点击保存,出现如下图6:
点击Back to the main page 回到main.cgi脚本。
此时数据库出现如下内容图7:
5. 交付
代码在链接处可以下载:
http://download.****.net/detail/notbaron/8965175
放置到cgi-bin解压即可。
6. PostgrelSQL和MySQL常用命令
mysql: show databases
psql: \l或\list
mysql: use dbname
psql: \c dbname
mysql: show tables
psql: \d
mysql: show columns from table name
psql: \d tablename
mysql: describe tablename
psql: \d+ tablename
mysql: quit 或者\q
psql:\q