Python基础编程案例之编写交互式博客系统

news2025/2/4 11:48:43

文章目录

    • 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中是对应的文章属性,包含一系列参数。

image-20220903103320348

当觉得一篇文章写的不如意时,就想着删除文章,下面来设计删除文章的函数,删除文章的函数很简单,重点是要理解这个逻辑。

删除文章的设计原理:

  • 定义函数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都是一条评论。

image-20220903144341009

对文章进行评论的函数设计原理:

  • 定义函数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结束函数的运行。
  • 如果文章不存在,则返回你要删除评论的文章不存在。
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

image-20220903164414183

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)

image-20220903165031998

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('参数不合法,请联系管理员!')

8、使用过程

image-20220903224525225

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/761885.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

WorkPlus AI助理:结合ChatGPT对话能力与企业数据,助力企业级AI构建!

WorkPlus AI助理是基于GPT和私有数据构建智能知识库和个性化AI,能够帮助企业生成博客、白皮书、社交媒体帖子、新闻稿等等,这些内容可以用于推广产品、服务,增强品牌形象和知名度。此外,利用WorkPlus AI助理还可以生成电子邮件、利…

基于linux串口实现语音刷抖音

目录 1.开发逻辑图及模块 2.编程实现语音和开发板通信 3.手机接入Linux热拔插相关,打开手机开发者模式允许USB调试 4.用shell指令来操作手机屏幕,模拟手动滑屏幕 5.最终主程序代码 1.开发逻辑图及模块 逻辑图: 模块 (1)语音…

读kafka生产端源码,窥kafka设计之道(上)

1. kafka 高吞吐之道-------异步提交批量发送 简约的发送接口----后面隐藏着并不简单的设计 kafka发送消息的接口非常简约,在简约的表面上,其背后却并不简单。先看下发送接口 kafkaProducer.send(new ProducerRecord(topic,msg), new Callback() {Ove…

8、链路层以太网协议,ARP协议32

网络层IP协议描述了通信中的起点到终点,但是数据不是飞过去的,是经过了大量的中间节点转发完成的。 一、以太网协议 1、MAC地址 物理硬件地址,是每一块网卡在出厂时设定的地址,固定且不可修改(早期,现在可…

当DevOps遇到AI,黑马迎来3.0时代丨IDCF

随着GhatGPT的爆火,人工智能和研发效能,无疑成为了2023的两个最重要的关键词。大规模语言模型LLM和相关应用的快速发展正在对研发团队的工作方式产生深远影响,这几乎象征着新的生产力革命的到来。 那么,作为一名工程师&#xff0…

Chat GPT是什么,初学者怎么使用Chat GPT,需要注意些什么

目录 Chat GPT是什么 初学者怎么使用Chat GPT 使用Chat GPT需要注意什么 一些简单的prompt示例 Chat GPT是什么 Chat GPT是由OpenAI开发的一种大型语言模型,它基于GPT(Generative Pre-trained Transformer)架构。GPT是一种基于深度学习的…

【Matlab】智能优化算法_遗传算法GA

【Matlab】智能优化算法_遗传算法GA 1.背景介绍2.数学模型3.文件结构4.详细代码及注释4.1 crossover.m4.2 elitism.m4.3 GeneticAlgorithm.m4.4 initialization.m4.5 Main.m4.6 mutation.m4.7 selection.m4.8 Sphere.m 5.运行结果6.参考文献 1.背景介绍 遗传算法(Ge…

(学习笔记)TCP 为什么是三次握手?不是两次、四次?

常规回答:“因为三次握手才能保证双方具有接收和发送的能力” 原因一:避免历史连接 三次握手的首要原因是为了防止旧的重复连接初始化造成混乱。 假设:客户端先发送了SYN(seq90)报文,然后客户端宕机了,而且这个SYN报…

一种电动汽车智能充电及收费云平台管理方案

摘要:对于电动汽车来说,主要是借助电力作为能源,有着多方面的优点。但是也存在着一定的问题,尤其在续航能力上相对较差。因此,在实际工作中要正确利用现代科学技术,让电动汽车实现智能充电。在研究中所涉及…

JavaScript中的let、const和var

在 JavaScript 中,let、const 和 var 是用于声明变量的关键字,在使用时有以下区别: 作用域:let 和 const 声明的变量具有块级作用域,只能在声明它的块中访问。而 var 声明的变量则是函数作用域或全局作用域&#xff0…

MS31001低压 5V DC 电机驱动

MS31001 是一款低压 5V 直流电机驱动芯片,为摄像机、 消费类产品、玩具和其他低压或者电池供电的运动控制类应用 提供了集成的电机驱动解决方案。 MS31001 能提供高达 0.8A 的输出电流。可以工作在 2.0~5.5V 的电源电压上。 MS31001 具有 PWM &#xff08…

NSSCTF随机一题

[GXYCTF 2019]Ping Ping Ping 应该是命令注入的题目,直接先ping一下本地,发现url栏有ip传参变化 接着就是利用命令注入符,尝试注入 它好像真的在ping,执行得特别慢,利用ls,查询到了flag文件 发现空格过…

LeetCode·每日一题·415. 字符串相加·模拟

作者:小迅 链接:https://leetcode.cn/problems/add-strings/solutions/2347085/mo-ni-zhu-shi-chao-ji-xiang-xi-by-xun-ge-fges/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商…

自适应巡航控制系统研究(Matlab代码实现)

目录 💥1 概述 📚2 运行结果 🎉3 参考文献 👨‍💻4 Matlab代码 💥1 概述 据统计, 我国交通事故造成的伤亡人数每年超过10万人, 其中驾驶员人为原因 (疲劳、酒驾、误操作等) 所致事故逐渐升高.汽车交通…

Python多线程同步编程Event使用方法

一、Event简介 Event是Python多线程同步编程中的一种同步原语,它可以帮助我们协调多个线程的操作,以达到线程间传递信号、同步操作等目的。 Event主要有两种状态:已设置和未设置。当Event被设置时,所有等待该Event的线程都会被唤…

数据结构-Java逆天操作

本文章会对Java线性表的相关知识进行讲解,也会以Java代码示例来进行解释 这里写目录标题 本文章会对Java线性表的相关知识进行讲解,也会以Java代码示例来进行解释对线性表的讲解分析定义可以表示为线性表可以用多种方式来表示和实现,常见的实…

数据结构与算法——什么是单链表,链式存储结构详解

前面详细地介绍了顺序表,本节给大家介绍另外一种线性存储结构——链表。 链表,别名链式存储结构或单链表,用于存储逻辑关系为 "一对一" 的数据。与顺序表不同,链表不限制数据的物理存储状态,换句话说&#…

基于 SpringBoot 的高校宿舍管理系统设计与开发

1.引言 宿舍是大学生学习与生活的主要场所之一,宿舍管理是高校学工管理事务中 尤为重要的一项。随着我国高校招生规模的进一步扩大,学生总体人数的不断增加, 宿舍管理工作变得愈加沉重和琐碎,学生宿舍信息的采集、汇总、统计与分析…

火山引擎A/B测试“广告投放实验”基础能力重构实践 (DataFunTalk渠道)

更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群 企业在进行营销推广时,广告投放通常是必备环节之一。为了避免投放“乱烧钱”,在大规模投放前,企业和广告优化师都会希望在多种广…

Web3时代来临:你准备好了吗?

如果你正在浏览本文,那么很可能你已经是Web3时代的一部分了,或者至少是将要成为其中的一员。因为Web3时代即将来临,它将彻底改变我们对互联网的认识和使用方式。 那么,什么是Web3时代呢?简单来说,它是指基于…