文章目录
- 1、博客系统的需求描述
- 2、面向用户层面各功能的设计思路与代码编写
- 2.1.定义文章库
- 2.2.文章的发布
- 2.3.删除文章
- 2.4.修改文章的标题以及内容
- 2.5.在评论区添加评论
- 2.6.删除文章中的某条评论
- 2.7.阅读文章
- 2.8.对文章进行点赞
- 2.9.对文章进行收藏
- 2.10.对文章进行打赏
- 2.11.查询指定文章的属性
- 3、面向后台管理层面各功能的设计思路与代码编写
- 3.1.统计后台文章的数量
- 3.2.文章数据查询
- 4.格式化打印文章字典库
- 5、功能验收
- 5.1.面向用户层面的各功能验收
- 5.2.面向后台管理层面的功能验收
- 6、增加博客导航
- 7、使用博客系统
- 8、使用过程
1、博客系统的需求描述
利用Python基础内容,编写一个博客系统,涵盖以下功能,后期有需求再优化:
面向用户层面的功能:
- 文章的发布。
- 删除文章。
- 修改文章的内容(包括文章的标题、内容)。
- 对文章进行评论以及删除文章的某个评论。
- 阅读文章。
- 对文章进行点赞、收藏、打赏。
- 查看某篇博文的属性(文章的总字数、点赞次数、收藏次数、评论次数、打赏次数、打赏收益)。
面向后台管理的功能:
- 统计文章库共存了多少篇文章。
- 统计所有博文的字数、文章的点赞数、收藏数、打赏次数。
- 统计本博客站点的打赏总收益额。
后续学了Python进阶还会优化这个项目。
2、面向用户层面各功能的设计思路与代码编写
2.1.定义文章库
首先定义一个文章库,所有的文章都存在这个文章库中,由于只是Python基础,还不掌握如何与MySQL连接,且不会数据库设计,因此我们以Python中的字典数据类型,去模拟一样文章库。
设计原理:
- 首先初始状态,是没有任何数据的,因此定义一个空的字典,当用户发布文章后将文章添加到字典库中。
articles = {}
2.2.文章的发布
文章发布主要用于用户发布文章的,用户发布文章就要考虑到用户发布的文章是不是完整的,例如标题有没有填写,文章内容有没有填写等等,都需要检测。
分为两部分,一部分是文章发布,一部分是检测文章和标题是否有不完整的地方,因此可以定义两个函数,一个函数用于发布文章,另一个函数用于检测文章是否完整,检测文章是否完整的函数会在新增文章里调用。
检测文章标题、内容是否为空的函数设计原理:
- 定义函数
check_title_content(**keyargs)
,形参是一个个数可变的关键字形参,用于接收文章的标题和内容。 - 在函数体内判断如果文章的标题和内容都为空的话,那么就输出“请输入文章的标题以及内容”。
- 如果文章标题的长度为0,就表示文章标题为空,那么就输出“文章标题不能为空”。
- 如果文章的内容长度为0,就表示文章内容为空,那么就输出“文章内容不能为空”。
- 个数可变的关键字形参,形参就相当于变量名,变量值就是一个字典,因此在判断标题、内容的长度时,就是看title、content对应的value长度是否为0,如果不明白keyargs的内容具体是啥,可以使用print打印keyargs观察就明白了。
- 如果文章的内容和长度都不为0,那么就返回一个True。
def check_title_content(**keyargs):
"""
:param **keyargs用于定义个数可变的关键字形参,因此必须同时传入title和content这两个关键字形参,否则会抛出异常
"""
if len(keyargs['title']) == 0 and len(keyargs['content']) == 0:
return '请输入文章的标题以及内容'
elif len(keyargs['title']) == 0:
return '文章标题不能为空'
elif len(keyargs['content']) == 0:
return '文章内容不能为空'
return True
新增文章的设计原理:
-
定义函数
add_atricles()
,不用传入任何形参。 -
在函数体内,使用input函数让用户输入文章的标题,然后让用户输入文章的内容。获取用户输入的文章标题和内容后,将其保存在变量里。文章标题保存在
title
标量里,文章内容保存在content
变量里。 -
然后调用
check_title_content(title=title, content=content)
函数,传入对应的关键字形参,将用户的标题和内容都传入check_title_content函数中去判断哪一部分为空,为空的一部分就会返回用户哪里为空,如果用户的文章标题和内容都完整,那么就返回一个True。 -
只需要判断check_title_content函数的返回结果是否为True,如果为True,就说明文章标题和内容都写完整了,可以存储到文章库里,否则就结束函数的运行,避免脏数据写入到文章库。
-
满足了上面的检测条件后,就可以去生成文章在字典里的键值对元素了:
- 首先生成文章的ID号,后面删除文章时可以根据ID将文章彻底的删除,因此文章的ID必定是字典中的父级Key。每篇文章的ID都不相同,可以使用len函数计算字典元素的个数,个数+1就是本次文章的ID号。
- 然后生成文章的属性,一篇文章有很多属性,包括文章的标题、内容、文章字数、点赞数、收藏数、打赏次数、打赏金额、评论等内容,由于文章的属性很多,在设计结构的时候,可以将文章的属性放在一个字典里,这个字典就可以作为ID的Value,也就是子字典,这样一来,文章ID和文章的属性就对应上了。
- 文章属性子字典中可以暂时设计以下几个键值对元素:
- title:文章的标题,value来源于用户传入的文章标题变量。
- content:文章的内容,value来源于用户传入的文章内容变量。
- words_num:文章的字数,value来源于通过len函数计算文章内容的长度。
- likes:点赞次数,初始值为0,后面会有单独的函数对文章进行点赞。
- collects:收藏次数,初始值为0,后面会有单独的函数对文章进行收藏。
- give_counts:打赏次数,初始值为0,后面会有单独的函数对文章进行打赏,并记录打赏的次数。
- gives:打赏金额,初始值为0,后面会有单独的函数对文章进行打赏。
- comments:评论区,文章的评论可能有很多,因此对于评论区的value也定义成一个字典,初始值为空字典,后面会有单独的函数在评论区中添加评论。
- 然后将文章的ID、文章的属性,以Key和Value的形式,追加到文章字典库中,即可完成文章的添加。
def add_atricles():
"""新增文章"""
global articles
# 接收用户写入的文章标题
title = input('请输入文章的标题:')
# 接收用户写入的文章内容
content = input('请输入文章内容:')
# 检查文章标题以及内容是否为空
check_resulf = check_title_content(title=title, content=content)
# 如果为空则结束函数的运行
if check_resulf != True:
print(check_resulf)
return
# 生成文章的id
art_id = len(articles) + 1
# id为字典中的父级Key,value为文章的属性,文章的属性是字典对象,在字典中包含多个键值对,每一个键值对都是文章的属性
#title为文章标题,content为文章内容,words_num为文章的字数,likes为文章点赞数,collects为文章收藏数,give_counts为文章打赏次数,gives为文章打赏金额,comments为文章的评论区
#最后将文章ID及对应的文章属性追加到文章字典库
articles[art_id] = {
'title': title,
'content': content,
'words_num': len(content),
'likes': 0,
'collects': 0,
'give_counts': 0,
'gives': 0,
'c
2.3.删除文章
经过各种函数的调用后,在文章字典库生成的一篇文章内容如下,父级Key是文章的ID,父级Value中是对应的文章属性,包含一系列参数。
当觉得一篇文章写的不如意时,就想着删除文章,下面来设计删除文章的函数,删除文章的函数很简单,重点是要理解这个逻辑。
删除文章的设计原理:
- 定义函数
del_atricles()
,不用传入任何形参。 - 在函数体汇总通过input函数接收用户要删除的文章标题,用户肯定不知道文章的ID是多少,因此用户只能根据文章的标题去删除。将要删除的文章标题存储在
title
变量里。 - 由于文章的标题、内容等之类的属性都在
articles
字典的父级Key的Value里,且父级Key的Value都是子字典,因此可以使用for循环去遍历这个字典,遍历字典时调用items
方法,将Key和Value转换成元组,利用元组多变量赋值的特性,每次循环时,将Key赋值给wzid
变量,将Value赋值给wzsx
变量,这样一来wzsx
变量里就包含了文章属性的字典。 - 我们就可以判断用户输入的文章标题是否在文字属性的字典里存在,如果存在才进行删除,否则就返回要删除的文章不存在,
- 当用户指定删除的文章在文章属性字典里存在,那么此次循环的
wzid
变量就是该文章的ID,将其赋值给del_wzid
变量,然后调用pop方法删除这个ID,删除了Key,对应的Value也就不存在了,文章也就成功被删除了。 - 函数只进行一次操作,因此当满足循环体中的if条件后,执行完对应的动作,就结束函数的运行,否则就是一个BUG。
def del_atricles():
"""删除文章"""
# 接收用户要删除问题的标题
title = input('请输入要删除的文章标题:')
#使用for循环去遍历文章字典库,遍历字典时调用items方法,将Key和Value转换成元组,利用元组多变量赋值的特性,每次循环时,将Key赋值给wzid变量,将Value赋值给wzsx变量,这样一来wzsx变量里就包含了文章属性的字典,每次循环时,判断用户要删除的文章是否在文章属性的字典里,如果存在,则找到文章对应的ID,将其在文章字典库中删除,并结束函数的运行,否则就返回要删除的文章不存在
for wzid, wzsx in articles.items():
if wzsx['title'] == title:
del_wzid = wzid
articles.pop(del_wzid)
delart_format = '文章:"{t}" 成功删除!'
print(delart_format.format(t = title))
return
else:
print('要删除的文章不存在!')
2.4.修改文章的标题以及内容
修改文章的标题和内容,在代码上很相似,因此我将这两个功能放在了一个函数了,因为修改文章的标题,也看会去修改文章的内容,那么只要是想对文章进行修改,首先询问要对文章标题进行修改吗,然后在询问要对文章的内容修改吗。
文章的标题修改和内容修改,返回的内容不同,因此将修改文章标题和修改文章内容的操作,分别放在两个函数里。
由于会询问用户是否要对xxx进行修改,因此还需要用户输入一个动作,修改标题和内容的动作都一样,因此通过一个函数来实现。
最后定义一个修改文章的函数,在里面会让用户输入要修改的文章标题,然后会调用捕捉用户动作的函数,在捕捉用户动作的函数中会根据传递的不同类型参数,去执行不同类型的修改操作函数,由于修改文章比较复杂,共用了四个函数。
1)修改文章标题的操作的函数设计原理:
- 先来定义一个函数
title_action_yes(wzsx)
,这个函数主要是执行修改文章标题的所有操作,其中wzsx形参用于接收for循环文章字典时的wzsx变量,这个函数肯定是在for循环文章字典库之后调用的,否则wzsx将没有实参传递。 - 首先定义一个变量
old_title
,用于记录修改标题前的文章标题。 - 然后使用input函数让用户输入文章新的标题,并赋值给变量
new_title
。 - 最后根据传入的wzsx变量实参,去修改文章属性字典中Key为’title’的value值,这样一来文章的标题就被更新了。
- 最后返回给用户文章的新旧标题。
def title_action_yes(wzsx):
"""
此函数用于修改文章的标题
:param:wzsx形参用于接收 for循环文章字典articles.items()时的wzsx变量,调用此函数时,就会传入wzsx变量,wzsx变量的对象就是文章属性的字典
"""
old_title = wzsx['title']
new_title = input('请输入新的文章标题:')
wzsx['title'] = new_title
print('"{o}" 文章的标题已更名为:"{n}"'.format(o=old_title, n=wzsx['title']))
2)修改文章内容的操作的函数设计原理:
修改文章内容的操作与修改文章标题的设计原理一样。
- 先来定义一个函数
content_action_yes(wzsx)
,这个函数主要是执行修改文章内容的所有操作,其中wzsx形参用于接收for循环文章字典时的wzsx变量,这个函数肯定是在for循环文章字典库之后调用的,否则wzsx将没有实参传递。 - 首先定义一个变量
old_content
,用于记录修改标题前的文章标题。 - 然后使用input函数让用户输入文章新内容,并赋值给变量
new_content
。 - 最后根据传入的wzsx变量实参,去修改文章属性字典中Key为’content’的value值,这样一来文章的内容就被更新了。
- 最后返回给用户文章的新旧内容。
def content_action_yes(wzsx):
"""
此函数用于修改文章的内容
:param:wzsx形参用于接收 for循环文章字典articles.items()时的wzsx变量,调用此函数时,就会传入wzsx变量,wzsx变量的对象就是文章属性的字典
"""
old_content = wzsx['content']
new_content = input('请输入新的文章内容:')
wzsx['content'] = new_content
print('"{t}"文章的旧内容为:\n\'\'\'{o}\'\'\' \n文章更新成功,新的内容为:\n\'\'\'{n}\'\'\''.format(t=wzsx['title'], o=old_content, n=wzsx['content']))
3)捕捉用户动作的函数设计原理:
- 定义函数
action(action, type_action, wzsx)
,此函数共接收三个形参,action用于接收用户输入的动作,type_action用于接收用户修改的类型,是修改标题还是修改文章内容,wzsx用于接收for循环文章字典时的wzsx变量。 - 首先判断action的值不是yes并且也不是no,如果满足这个条件,就说明用户输入的动作参数不正确,此时就会定义一个for循环,循环三次,也就是说,在三次内,有一次输入的动作参数为yes或者是no,就会去执行对应的代码,如果三次内都没有输入正确,那么就返回参数不合法。
- for循环会循环3次,在循环体中会让用户输入yes或者no,并且赋值给当action_again变量,第三次循环还没有输入正确的参数时,将会打印参数不合法。
- 在循环体中,如果用户输入的是yes,那么就判断type_action形参的值,如果这个形参的值为title_action,就说明要对文章的标题进行修改,那么就调用
title_action_yes(wzsx)
这个函数传入wzsx变量,对文章的标题进行修改,如果type_action形参的值为content_action,说明要对文章的内容进行修改,那么就调用content_action_yes(wzsx)
这个函数传入wzsx变量,对文章的内容进行修改,一次处理后使用return结束函数。 - 在循环体中,如果用户输入的是no,那么就打印不对文章属性进行修改,使用return结束函数。
- 如果用户一开始就输对了动作参数,当动作参数为yes,如果type_action形参的值为title_action,就说明要对文章的标题进行修改,那么就调用
title_action_yes(wzsx)
这个函数传入wzsx变量,对文章的标题进行修改,如果type_action形参的值为content_action,说明要对文章的内容进行修改,那么就调用content_action_yes(wzsx)
这个函数传入wzsx变量,对文章的内容进行修改,一次处理后使用return结束函数。 - 如果用户一开始就输对了动作参数,当动作参数为no,那么就打印不对文章属性进行修改,使用return结束函数。
- 当用户输入的文章不存在时,那么就返回你要修改的文章不存在。
def action(action, type_action, wzsx):
"""
此函数既可以修改文章的标题,又可以修改文章的内容,主要根据type_action来识别修改的是标题还是内容
:param action: action的值为yes或者no,如果非yes、no会让用户重新输入,重输入的次数为3,如果重输入时,有一次输对了,那么就会在循环体内根据条件对文章进行修改
:param type_action: 当type_action的值为title_action时,就会调用修改文章标题的函数执行修改文章标题的相关操作
当type_action的值为content_action时,就会调用修改文章内容的函数执行修改文章内容的相关操作
:param wzsx: 值为wzsx,wzsx是for循环字典库Key和Value中Value部分的内容,wzx包含了所有的文章属性,包括标题、内容等等
"""
#print(action, type_action, wzsx) 调试使用
if action != 'yes' and action != 'no':
# 当action的值不是yes、no时,可以重复输入三次,如果三次输入的都不对,则打印参数不合法,如果三次中有一次输入对了,就会根据对应的动作参数,执行对应的代码,完成文章的修改
for i in range(1, 4):
action_again = input('请输入[yes|no]:')
if action_again == 'yes':
# 当重复输入过程中输入了yes,则判断type_action的值,如果是title_action则修改文章的标题,调用title_action_yes(wzsx)函数处理,如果是content_action则修改文章的内容,调用函数content_action_yes(wzsx)处理,函数执行完成后使用return跳出循环,结束yes、no的重复
if type_action == 'title_action':
title_action_yes(wzsx)
return
elif type_action == 'content_action':
content_action_yes(wzsx)
return
elif action_again == 'no':
print('不对文章属性进行修改。')
return
#重复三次都没有输对,则返回参数不合法,请联系管理员
else:
if i == 3:
print('参数不合法,请联系管理员~')
# 当action为yes时,就说明用户一次就输对了操作,判断是对文章标题操作还是对文章的内容操作,然后调用对应的函数,函数执行完后使用return结束
elif action == 'yes':
# 对于文章的标题使用title_action_yes函数处理
if type_action == 'title_action':
title_action_yes(wzsx)
return
# 对于文章的内容使用content_action_yes函数处理
elif type_action == 'content_action':
content_action_yes(wzsx)
return
elif action == 'no':
print('不对文章属性进行修改。')
return
4)修改文章的函数设计原理
这个函数就是修改文章的主函数了,在这个函数中会让用户输入要修改的文章标题,然后去遍历文章字典,当用户输入的文章在后台文章库时,询问用户是否要对文章标题进行修改,如果修改则调用捕捉用户动作的函数完成对文章标题的修改,随后询问用户是否要对文章内容进行修改,如果修改,也调用捕捉用户动作的函数完成对文章内容的修改,当用户输入的文章不存在后台文章库时,则返回你要修改的文章不存在。
- 定义
update_atricles()
,不需要传递任何参数。 - 首先使用input函数,让用户输入要修改的文章标题,然后将标题赋值给title变量。
- 接下来进行for循环遍历,遍历文章字典库,取到文章的id以及文章属性的变量,和前面的删除文章一个套路。
- 然后判断用户传入的文章是否在后台的文章字典库中,如果存在,那么就使用input函数“返回文章存在,是否要对文章的标题进行修改”,让用户传入一个动作,该动作会赋值给action_format变量。
- 然后调用
action(action = title_action, type_action = 'title_action', wzsx = wzsx)
函数,传入这些实参,完成对文章标题的修改。 - 标题、内容都修改完成后,使用return结束函数。
- 当文章标题修改完成后,开始询问用户是否要对文章的内容进行修改,套路都一样。
def update_atricles():
"""修改文章"""
title = input('请输入要修改的文章标题:')
#循环遍历文章字典库,将文章的id(Key)放在wzid变量里,将文章的属性(Value)放在wzsx变量里
for wzid, wzsx in articles.items():
#修改文章的标题
if wzsx['title'] == title:
#up_wzid = wzid
#print('要修改的文章id:', up_wzid)
#input函数只能输入一个参数,当需要输入两个参数时,可以使用格式化字符串
action_format = '后台查询到{t}文章存在,是否要对文章标题进行修改[yes|no]:'
title_action = input(action_format.format(t=wzsx['title']))
action(action = title_action, type_action = 'title_action', wzsx = wzsx)
#随后询问用户是否也要对这个标题对应的文章进行修改
content_format = '"{t}"的文章内容为:\n{c} \n是否要对文章内容进行修改[yes|no]:'
content_action = input(content_format.format(t=wzsx['title'], c=wzsx['content']))
action(action = content_action, type_action = 'content_action', wzsx = wzsx)
return
else:
print('你要修改的文章不存在!')
2.5.在评论区添加评论
接下来设计文章的评论区,一片文章一般会有0~n条评论,因此如果将每条评论的都已键值对的形式存储在文章ID对应的Value子字典里,势必会导致子字典很长,太臃肿,因此一开始在设计文章的字典库时,就将评论区以字典的方式进行了存储,如下图所示,文章的ID是父级Key,父级Key的Value是文章的所有属性,父级Key的Value是一个字典,评论区是文章的一种属性,其对于的Key也是一个字典,在这个字典中n个Key,每个Key的Value都是一条评论。
对文章进行评论的函数设计原理:
-
定义函数
add_comment()
,不需要传递任何参数。 -
首先让用户输入对哪篇文章进行评论,然后将文章的标题存储到
title
变量里。 -
然后使用老套路,通过for循环遍历文章字典库,每次循环时将文章的属性放在wzsx变量里。
-
判断用户输入的文章是否在文章字典库中,如果存在,则让用户输入要发表的评论.
-
一个文章可能存在多条评论内容,我们不能确定评论有多少条,所有的评论虽然都在字典中充当Value,但是Value总要对应Key的,评论对应的Key可以由comment+当前评论的ID组成,因此接下来需要生成生成评论的ID,评论的ID可以通过len函数计算comments的Value中字典共有多少个元素,计算出来的数+1就是当前评论的ID,文章中每条评论的ID都不同。生成完评论的ID后,再生成本次评论的Key,评论的Key由comment+评论ID组成。
-
评论内容、本次评论的Key名都准备完成后,就可以在评论区字典中增加评论键值对,完成评论的发表,然后使用return结束函数。
-
当用户输入的文章不存在时,则返回你要评论的文章不存在。
另外这里再提一点,为什么不接着使用for循环去遍历评论区的字典,然后追加评论到字典里,那是因为评论区位于文章属性字典里,文章属性的字典里只有这一个元素的Value是一个字典,因此不能再使用for循环去遍历评论区字典,另外一个文章可能在添加评论之前,是没有评论的,也就意味着评论区为空,也是无法去循环遍历的。
评论区的字典相当于文章字典的子字典,因此可以使用二维字典的方法去追加元素:
wzsx['comments'][comment_key] = comment
。
def add_comment():
"""
对某个文章进行评论
"""
title = input('请输入要对哪篇文章进行评论:')
for wzid, wzsx in articles.items():
#对文章进行评论
if wzsx['title'] == title:
comment = input('请发表评论:')
#生成当前评论的ID号,每条评论的ID不同,当前评论区的评论数+1就是当前评论的ID号
comment_id = len(wzsx['comments']) + 1
#生成当前评论所在字典中的Key,由comment+评论ID组成
comment_key = 'comment' + str(comment_id)
#在评论区添加评论
wzsx['comments'][comment_key] = comment
#wzsx['comment']['comment' + str(comment_id)]= comment
return
else:
print('你要评论的文章不存在!')
2.6.删除文章中的某条评论
删除评论和发表评论也很像,但是删除评论时就可以使用for循环遍历评论区的字典,因为此时字典中肯定有评论。
- 定义函数
del_comment()
,不需要传递任何参数。 - 首先使用inpu函数,让用户输入要对哪篇文章的评论进行删除,将文章的标题赋值给title变量。
- 然后使用for循环遍历文章字典库,获取文章属性的字典,赋值给wzsx变量,当要删除评论的文章存在于字典库时,就让用户输入要删除那条评论,并将其存储在comment变量中:
- 此时就再使用for循环遍历评论区字典
wzsx['comments'].items()
,当要删除的评论在评论区时,就使用pop方法删除这条评论,否则就提示要删除的评论不存在,只要删除了评论,就使用return结束函数的运行。
- 此时就再使用for循环遍历评论区字典
- 如果文章不存在,则返回你要删除评论的文章不存在。
def del_comment():
"""删除对某发个文章的某条评论"""
title = input('请输入要对哪篇文章的评论进行删除:')
for wzid, wzsx in articles.items():
#判断要删除评论的文章存在否
if wzsx['title'] == title:
comment = input('请输入要删除的评论:')
#遍历comment评论的字典,判断删除的那条评论是否存在,如果存在则删除,否则返回评论不存在
for comkey,comvalue in wzsx['comments'].items():
if comvalue == comment:
wzsx['comments'].pop(comkey)
comdelformat = '"{t}"文章中的"{c}"评论已被删除。'
print(comdelformat.format(t=title, c=comvalue))
#对字典中的键值对进行修改后,记得跳出循环,否则就会抛出异常:dictionary changed size during iteration
return
else:
print('要删除的评论不存在!')
#if中包含了for,for中又包含了if,为了避免多次循环,第一个if满足条件后,就return结束函数
return
else:
print('你要删除评论的文章不存在!')
2.7.阅读文章
阅读文章的函数设计原理:
-
定义函数
search_atricles()
,不传入任何参数。 -
使用input函数让用户输入要阅读的文章,然后赋值给title变量。
-
使用for循环去遍历文章字典库,当文章的标题在文章属性字典中存在时,就返回文章的内容,否则就打印要阅读的文章不存在。
-
当文章存在时,就将文章属性字典中的content的Value使用get方法打印出来。
def search_atricles():
"""阅读某篇文章"""
title = input('请输入要阅读的文章:')
for wzid, wzsx in articles.items():
if wzsx['title'] == title:
search_format = '"{t}"文章的内容为:\n{c}'
print(search_format.format(t = wzsx['title'], c = wzsx.get('content')))
return
else:
print('要阅读的文章不存在!')
2.8.对文章进行点赞
对文章点赞的函数设计原理:
- 定义函数
atr_like()
,不传入任何参数。 - 使用input函数让用户输入要点赞的文章,然后赋值给title变量。
- 使用for循环去遍历文章字典库,当文章的标题在文章属性字典中存在时,就对文章进行点赞,否则就提示要点赞的文章不存在。
- 当文章存在时,就将文章属性字典中likes的Value值+1,实现累加的效果,并返回点赞成功,然后使用return结束函数。
def atr_like():
"""对指定的文章点赞"""
title = input('请输入要点赞的文章:')
for wzid, wzsx in articles.items():
if wzsx['title'] == title:
wzsx['likes'] += 1
print('点赞成功~')
return
else:
print('要点赞的文章不存在!')
2.9.对文章进行收藏
对文章点赞的函数设计原理:
- 定义函数
atr_collect()
,不传入任何参数。 - 使用input函数让用户输入要收藏的文章,然后赋值给title变量。
- 使用for循环去遍历文章字典库,当文章的标题在文章属性字典中存在时,就对文章进行收藏,否则就提示要收藏的文章不存在。
- 当文章存在时,就将文章属性字典中collects的Value值+1,实现累加的效果,并返回收藏成功,然后使用return结束函数。
def atr_collect():
"""对指定的文章收藏"""
title = input('请输入要收藏的文章:')
for wzid, wzsx in articles.items():
if wzsx['title'] == title:
wzsx['collects'] += 1
print('收藏成功~')
return
else:
print('要收藏的文章不存在!')
2.10.对文章进行打赏
- 定义函数
atr_give()
,不需要传入任何参数。 - 使用input函数让用户输入要打赏的文章,然后赋值给title变量。
- 使用for循环去遍历文章字典库,当文章的标题在文章属性字典中存在时,就对文章进行打赏,否则就提示要打赏的文章不存在。
- 当文章存在时,就让用户输入打赏的金额,然后判断打赏的金额是否是数字,如果是数字的话,将打赏的金额转换成小数,并且将文章属性字典中gives的Value值+打赏的金额,并且将打赏次数也+1,即对文章属性字典中give_counts的Value值+1,实现打赏金额、打赏次数累加的效果。另外当打赏的金额不是数字时,提示输入正确的打赏金额。
- 打赏完成后使用return结束函数的运行。
def atr_give():
"""对指定的文章打赏"""
title = input('请输入要打赏的文章:')
for wzid, wzsx in articles.items():
if wzsx['title'] == title:
give_format = '请输入要对{t}文章打赏的金额:'
give = input(give_format.format(t = title))
# 如果打赏的金额是数字,那么就将其转换成小数,然后将金额和当前字典中give的value进行累加,将历次打赏的金额都累加在一起,并且每次打赏,打赏次数+1
if give.isdigit():
wzsx['gives'] += float(give)
wzsx['give_counts'] += 1
print('打赏成功~')
return
else:
print('请输入正确的打赏金额!')
return
else:
print('要打赏的文章不存在!')
2.11.查询指定文章的属性
用户可以浏览一片文章的属性,例如文章的总字数、点赞次数、收藏次数、评论次数、打赏次数、收藏次数。
- 定义函数
search_atr_pro()
,不需要传入任何参数。 - 使用input函数让用户输入要收藏的文章,然后赋值给title变量。
- 使用for循环去遍历文章字典库,当文章的标题在文章属性字典中存在时,就打印文章的属性,否则就提示文章不存在。
- 文章的属性都位于文章字典库的文章属性字典里,直接打印即可,对于评论次数可以使用len函数取获取。
def search_atr_pro():
"""查看指定文章的属性"""
title = input('请输入要查看属性的文章:')
for wzid, wzsx in articles.items():
if wzsx['title'] == title:
pro_format = '"{t}"文章的总字数为{w}、点赞次数为"{l}、收藏次数为{c}、评论次数为{csc}、打赏次数为{gc}、打赏收益为{gv}'
print(pro_format.format(t = wzsx['title'], w = wzsx['words_num'], l = wzsx['likes'], c = wzsx['collects'], csc = len(wzsx['comments'].values()) , gc = wzsx['give_counts'], gv = wzsx['gives']))
return
else:
print('要查看属性的文章不存在!')
3、面向后台管理层面各功能的设计思路与代码编写
3.1.统计后台文章的数量
非常简单,只需要通过len函数获取文章字典库的元素个数即可。
def atricles_nums():
"""统计后台文章数量"""
atr_count = len(articles)
print('后台文章字典库共有"{}"篇文章。'.format(atr_count))
3.2.文章数据查询
该功能可以统计所有博文的点赞次数、所有博文的收藏次数、所有博文的打赏次数、所有博文的评论次数、所有博文的总字数、所有博文的总收益额。
所有功能的实现套路都一样,都是数据查询,仅说一个所有博文的点赞次数是如何实现的。
- 定义函数
sta_art(status)
,这个函数需要传入参数,因为每个统计的功能都集成在了这一个函数里,status的取值范围:1为所有博文点赞次数,2为所有博文收藏次数,3为所有博文打赏次数,4、所有博文的评论次数,5为所有博文总字数, 6为博文总收益额 - 当status等于1的时候,就是对所有博文的点赞数进行统计,首先定义一个初始的总点赞数变量,值为0,然后使用for循环遍历文章字典库,取出每篇博文的点赞数,与总点赞数变量相加,即可得到总点赞次数。
def sta_art(status):
"""根据传的参数判断要统计的项目,1为所有博文点赞次数,2为所有博文收藏次数,3为所有博文打赏次数,4、所有博文的评论次数,5为所有博文总字数, 6为博文总收益额"""
if status == 1:
total_likes = 0
for wzid, wzsx in articles.items():
total_likes += wzsx['likes']
tl_format = '所有博客累计点赞次数为:"{tl}"'
print(tl_format.format(tl = total_likes))
elif status == 2:
total_collects = 0
for wzid, wzsx in articles.items():
total_collects += wzsx['collects']
tc_format = '所有博客累计收藏次数为:"{tc}"'
print(tc_format.format(tc = total_collects))
elif status == 3:
total_gcs = 0
for wzid, wzsx in articles.items():
total_gcs += wzsx['give_counts']
gcs_format = '所有博客累计打赏次数为:"{gcs}"'
print(gcs_format.format(gcs = total_gcs))
elif status == 4:
total_csc = 0
for wzid, wzsx in articles.items():
total_csc += len(wzsx['comments'])
csc_format = '所有博客累计评论次数为:"{csc}"'
print(csc_format.format(csc = total_csc))
elif status == 5:
total_fc = 0
for wzid, wzsx in articles.items():
total_fc += wzsx['words_num']
fc_format = '所有博客累计文字数为:"{fc}"'
print(fc_format.format(fc = total_fc))
elif status == 6:
total_earn = 0
for wzid, wzsx in articles.items():
total_earn = total_earn + wzsx['gives']
ear_format = '博客打赏累加收益额为:"{te}"'
print(ear_format.format(te=total_earn))
else:
print('参数不正确!')
4.格式化打印文章字典库
atr_db = json.dumps(articles, indent=4,ensure_ascii=False, sort_keys=False,separators=(',', ':'))
print(atr_db)
5、功能验收
5.1.面向用户层面的各功能验收
#发布文章
add_atricles()
add_atricles()
add_atricles()
#删除指定的文章
del_atricles()
#修改指定的文章
update_atricles()
#对指定的文章发表评论
add_comment()
add_comment()
add_comment()
add_comment()
#对指定的文章删除评论
del_comment()
#阅读指定的文章
search_atricles()
#对指定的文章点赞
atr_like()
atr_like()
#对指定的文章收藏
atr_collect()
atr_collect()
#对指定的文章打赏
atr_give()
atr_give()
atr_give()
#查询指定文章的属性
search_atr_pro()
输出的内容:
D:\软件\Python\python.exe G:/Python全栈运维开发/Python-基础语法/代码文件/简单的个人博客小系统b3.py
简单的个人博客系统
请输入文章的标题:第一篇文章
请输入文章内容:在定义函数时,我们可以强制某个形参必须使用关键字传参,如果不用关键字传参则会抛出异常。
请输入文章的标题:第二篇文章
请输入文章内容:强制某个形参使用关键字传参,做法也很简单,只需要在形参的前面添加一个`*`号,这样一来,`*`号后面所有的形参都会被设置成强制关键字传参,只能接受关键字传参过来的实参。
请输入文章的标题:第三篇文章
请输入文章内容:哈哈哈
请输入要删除的文章标题:第三篇文章
文章:"第三篇文章" 成功删除!
请输入要修改的文章标题:第一篇文章
后台查询到第一篇文章文章存在,是否要对文章标题进行修改[yes|no]:yes
请输入新的文章标题:第①篇:Python函数中的星号参数
"第一篇文章" 文章的标题已更名为:"第①篇:Python函数中的星号参数"
"第①篇:Python函数中的星号参数"的文章内容为:
在定义函数时,我们可以强制某个形参必须使用关键字传参,如果不用关键字传参则会抛出异常。
是否要对文章内容进行修改[yes|no]:yes
请输入新的文章内容:定义函数时,如果无法事先确定传递的位置实参的个数,在这种情况下,可以将形参定义为个数可变的位置形参,去接收0个或多个实参,传进来的多个实参最终会被转换成一个元组类型,赋值给形参变量。
"第①篇:Python函数中的星号参数"文章的旧内容为:
'''在定义函数时,我们可以强制某个形参必须使用关键字传参,如果不用关键字传参则会抛出异常。'''
文章更新成功,新的内容为:
'''定义函数时,如果无法事先确定传递的位置实参的个数,在这种情况下,可以将形参定义为个数可变的位置形参,去接收0个或多个实参,传进来的多个实参最终会被转换成一个元组类型,赋值给形参变量。'''
请输入要对哪篇文章进行评论:第①篇:Python函数中的星号参数
请发表评论:大佬写的太好了,感谢分享
请输入要对哪篇文章进行评论:第①篇:Python函数中的星号参数
请发表评论:学到新技术了
请输入要对哪篇文章进行评论:第①篇:Python函数中的星号参数
请发表评论:彩
请输入要对哪篇文章进行评论:第①篇:Python函数中的星号参数
请发表评论:6666
请输入要对哪篇文章的评论进行删除:第①篇:Python函数中的星号参数
请输入要删除的评论:6666
"第①篇:Python函数中的星号参数"文章中的"6666"评论已被删除。
请输入要阅读的文章:第①篇:Python函数中的星号参数
"第①篇:Python函数中的星号参数"文章的内容为:
定义函数时,如果无法事先确定传递的位置实参的个数,在这种情况下,可以将形参定义为个数可变的位置形参,去接收0个或多个实参,传进来的多个实参最终会被转换成一个元组类型,赋值给形参变量。
请输入要点赞的文章:第①篇:Python函数中的星号参数
点赞成功~
请输入要点赞的文章:第①篇:Python函数中的星号参数
点赞成功~
请输入要收藏的文章:第①篇:Python函数中的星号参数
收藏成功~
请输入要收藏的文章:第①篇:Python函数中的星号参数
收藏成功~
请输入要打赏的文章:第①篇:Python函数中的星号参数
请输入要对第①篇:Python函数中的星号参数文章打赏的金额:777
打赏成功~
请输入要打赏的文章:第①篇:Python函数中的星号参数
请输入要对第①篇:Python函数中的星号参数文章打赏的金额:67
打赏成功~
请输入要打赏的文章:第①篇:Python函数中的星号参数
请输入要对第①篇:Python函数中的星号参数文章打赏的金额:25
打赏成功~
请输入要查看属性的文章:第①篇:Python函数中的星号参数
"第①篇:Python函数中的星号参数"文章的总字数为43、点赞次数为"2、收藏次数为2、评论次数为3、打赏次数为3、打赏收益为869.0
{
"1":{
"title":"第①篇:Python函数中的星号参数",
"content":"定义函数时,如果无法事先确定传递的位置实参的个数,在这种情况下,可以将形参定义为个数可变的位置形参,去接收0个或多个实参,传进来的多个实参最终会被转换成一个元组类型,赋值给形参变量。",
"words_num":43,
"likes":2,
"collects":2,
"give_counts":3,
"gives":869.0,
"comments":{
"comment1":"大佬写的太好了,感谢分享",
"comment2":"学到新技术了",
"comment3":"彩"
}
},
"2":{
"title":"第二篇文章",
"content":"强制某个形参使用关键字传参,做法也很简单,只需要在形参的前面添加一个`*`号,这样一来,`*`号后面所有的形参都会被设置成强制关键字传参,只能接受关键字传参过来的实参。",
"words_num":84,
"likes":0,
"collects":0,
"give_counts":0,
"gives":0,
"comments":{}
}
}
进程已结束,退出代码0
5.2.面向后台管理层面的功能验收
#查询指定文章的属性
search_atr_pro()
#统计后台文章的数量
atricles_nums()
#查询所有博文的点赞次数
sta_art(1)
#查询所有博文的收藏次数
sta_art(2)
#查询所有博文的打赏次数
sta_art(3)
#查询所有博文的评论次数
sta_art(4)
#查询所有博文的总字数
sta_art(5)
#查询所有博文的总收益额
sta_art(6)
6、增加博客导航
博客应该存在一个导航页面,用户根据博客的功能进行一系列的操作。
def main():
menu_format = '===============================================================================' \
'\n={project}=' \
'\n={sep}{add_atricles}{sep}{del_atricles}{sep}{update_atricles}{sep}=' \
'\n={sep}{add_comment}{sep}{del_comment}{sep}{search_atricles}{sep}=' \
'\n={sep}{atr_like}{sep}{atr_collect}{sep}{atr_give}{sep}=' \
'\n={sep}{search_atr_pro}{sep}{del_comment}{sep}{search_atricles}{sep}=' \
'\n={sep}{add_comment}{sep}{atricles_nums}{sep}{sta_art}{sep}=' \
'\n={sep}{search_all}{sep}{quit}{sep}{sep}{sep} =' \
'\n==============================================================================='
print(menu_format.format(project='[Python博客系统]'.center(75, '·'), sep=' '.ljust(10, ' '),
add_atricles='1-->发布文章'.ljust(10, ' '), del_atricles='2-->删除文章'.ljust(10, ' '),
update_atricles='3-->修改文章 '.ljust(10, ' '),
add_comment='4-->发表评论'.ljust(10, ' '), del_comment='5-->删除评论'.ljust(10, ' '),
search_atricles='6-->阅读文章'.ljust(10, ' '),
atr_like='7-->点赞文章'.ljust(10, ' '), atr_collect='5-->收藏文章'.ljust(10, ' '),
atr_give='6-->打赏文章'.ljust(10, ' '),
search_atr_pro='8-->文章属性'.ljust(10, ' '), atricles_nums='9-->总文章量'.ljust(10, ' '),
sta_art='6-->后台统计'.ljust(10, ' '),
search_all='13-->所有文章'.ljust(10, ' '), quit='q-->退出博客系统').ljust(10, ' '))
7、使用博客系统
while True:
main()
oper = input('你要进行什么操作:')
print(oper)
if oper == "1":
add_atricles()
elif oper == "2":
del_atricles()
elif oper == "3":
update_atricles()
elif oper == "4":
add_comment()
elif oper == "5":
del_comment()
elif oper == "6":
search_atricles()
elif oper == "7":
atr_like()
elif oper == "8":
atr_collect()
elif oper == "9":
atr_give()
elif oper == "10":
search_atr_pro()
elif oper == "11":
atricles_nums()
elif oper == "12":
sta_art(1)
sta_art(2)
sta_art(3)
sta_art(4)
sta_art(5)
sta_art(6)
elif oper == "13":
atr_db = json.dumps(articles, indent=4, ensure_ascii=False, sort_keys=False, separators=(',', ':'))
print(atr_db)
elif oper == "q":
exit('期待下次使用博客系统~')
else:
print('参数不合法,请联系管理员!')