最新消息:欢迎光临 魔力 • Python!大家可以点开导航菜单中的【学习目录】,这个目录类似图书目录,更加方便学习!

练习项目13:简单的BBS功能(上)

Python教程 小楼一夜听春语 5868浏览 0评论

这个练习项目来自《Python基础教程(第2版)》,案例原名为“自定义电子公告板”。

练习包括两个阶段:

  • 第一阶段:实现与PostgreSQL的连接与数据操作,并将数据呈现为网页。
  • 第二阶段:实现消息列表、查看消息、编辑消息、回复消息和保存信息等功能。

本篇教程我们完成第一阶段。

一、创建数据库与数据表

大家可以参考《PostgreSQL数据库简易安装教程》完成数据库以及表的创建。

除了《PostgreSQL数据库简易安装教程》中创建数据库与数据表的SQL语句,这里再给大家列出一些当前项目准备过程中可能需要用到的语句。

此处以数据库“myproject_db”和数据表“messages”以及用户“opython”简单举例。

注意:红色部分加粗部分均为可变内容,并且,SQL Shell中命令结束加分号“;”才能够执行。

<- 删除数据库 ->
drop database myproject_db;

<- 添加超级用户 ->
create user opython with superuser password ‘123456‘;

<- 修改密码 ->
alter user opython with password ‘654321‘;

<- 删除用户名 ->
drop user opython ;

<- 删除数据表 ->
drop table messages;

<- 添加数据行 ->
insert into messages(列名1,列名2,…) values (值1,值2,…);

<- 查询数据行 ->

select * from messages;

select subject,text from messages where id=1;

 

在进行下一步之前,如果还没有创建数据表“messages”的话,可以通过如下语句进行创建。

示例代码:

<- 创建数据表 ->
create table messages(
id serial primary key,
subject text not null,
sender text not null,
reply_to integer references messages,
text text not null
);

这里,我对每一列的名称做一下解释:

  • id:消息序号,serial表示自动增长的数字,primary key表示这一列是不可重复的主键。
  • subject:消息标题,text表示文本类型,not null表示不可为空值。
  • sender:消息发送人。
  • reply_to:被回复消息序号,integer表示整数类型,references messages表示引用messages表的主键,也就是说被回复消息的序号必须是messages表中主键序号之一,即只有已存在表中的消息才能被回复。
  • text:消息内容。

二、尝试与数据库进行连接

与数据库进行连接,我们需要使用到psycopg2模块。

通过psycopg2模块中的connect()方法与数据库进行连接。

注意,connect()方法中参数的提供有两种不同的写法。

示例代码:

import psycopg2

conn = psycopg2.connect(database='myproject_db', user='opython', password='opython')  # 连接数据库
# 另一种写法:conn=psycopg2.connect('user=opython password=opython dbname=myproject_db ')
curs = conn.cursor()  # 获取游标对象
sql = 'select * from messages'
curs.execute(sql)  # 执行SQL语句
print(curs.fetchall())  # 显示输出所有查询结果

当我们运行代码,我们能够看到由数据库中所有数据行元组所组成的列表。

当然,如果数据库中没有任何数据,只会显示一个空列表。

到这里,我们已经能够成功的进行数据库的访问。

三、尝试向数据库中添加数据

我们可以通过input()函数模拟获取用户输入,然后根据输入中是否有被回复消息的序号来决定如何插入新的数据。

这个功能实现起来很简单,请大家参考示例代码进行理解。

示例代码:

import psycopg2

subject = input('标题:')
sender = input('发送人:')
reply_to = input('回复给:')
text = input('内容:')

if reply_to:  # 如果是回复已有消息
    sql = "insert into messages(subject,sender,reply_to,text) values('%s','%s',%s,'%s')" % (
        subject, sender, reply_to, text)
else:  # 否则是发布新的消息
    sql = "insert into messages(subject,sender,text) values('%s','%s','%s')" % (subject, sender, text)

conn = psycopg2.connect(database='myproject_db', user='postgres', password='opython')
curs = conn.cursor()
curs.execute(sql)
conn.commit()  # 提交数据操作
sql = 'select * from messages'
curs.execute(sql)
print(curs.fetchall())

运行上方代码之后,我们就能够向数据库中添加新的内容了。

四、查询数据并输出到HTML

输出的网页内容如下图:

我们可以在PyCharm中先新建一个HTML文件,编写页面代码。

示例代码:(HTML)

<!DOCTYPE html>
<html lang="zh_cn">
<head>
    <meta charset="gbk">
    <title>我的论坛</title>
</head>
<body>
<h3>小楼帅哥的第一个BBS</h3>

<b><font size="2">id.发送人:消息标题</font></b><br/>
<font size="2">消息内容</font>
<blockquote>
    <b><font size="2">id.回复人:回复标题</font></b><br/>
    <font size="2">回复内容</font>
</blockquote>

</body>
</html>

接下来,我们可以新建一个CGI或py脚本,将这些HTML代码复制到脚本代码中使用。

示例代码:

import psycopg2.extras

conn = psycopg2.connect(database='myproject_db', user='opython', password='opython')
curs = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)  # 参数是以字典形式获取查询结果

print('''
<!DOCTYPE html>
<html lang="zh_cn">
<head>
    <meta charset="gbk">
    <title>我的论坛</title>
</head>
<body>
    <h3>小楼帅哥的第一个BBS</h3>
''')

sql = 'select * from messages'
curs.execute(sql)
messages = curs.fetchall()
top_level = []  # 保存父级消息的列表
children = {}  # 保存子级消息的字典

for message in messages:  # 遍历返回的消息列表
    parrent_id = message['reply_to']  # 获取消息元组中的reply_to列
    if parrent_id is None:  # 如果不是回复的消息
        top_level.append(message)  # 添加到父级消息列表
    else:
        children.setdefault(parrent_id, []).append(message)  # 否则以被回复消息的序号为键添加回复消息到值的列表


def format_show(message):
    print('<h5>{}.{}:{}</h5>'.format(message['id'], message['sender'], message['subject']))  # 输出父级消息内容
    print('<font size="2">{}</font>'.format(message['text']))
    try:
        kids = children[message['id']]  # 根据父级消息id从子级消息字典中查找所有子级消息
    except KeyError:
        pass
    else:
        print('<blockquote>')
        for kid in kids:  # 遍历找到的消息列表
            format_show(kid)  # 递归进行下一级消息的处理
        print('</blockquote>')


print('<p>')
for message in top_level:  # 遍历父级消息
    format_show(message)  # 调用递归函数进行多级遍历

print('''
</p>
</body>
</html>
''')

在上方代码中,重点内容是所有消息的输出使用到了递归函数。

基本原理是:读取一条顶级消息时,调用递归函数,将顶级消息输出到页面,然后以顶级消息的id为键,获取到子级消息字典中对应的值的列表。然后,再对子级消息进行遍历,将子级消息作为父级消息再次调用递归函数。

到这里,我们就完成了第一阶段的练习。

本节练习源代码:【点此下载

 

转载请注明:魔力Python » 练习项目13:简单的BBS功能(上)

头像
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网站 (可选)