Python 数据库开发实战 - Python与Redis交互篇- 缓存新闻数据至redis

news2025/5/28 4:20:32

实现新闻缓存功能 - “news_dao.py” - 从数据库提取明确的新闻数据保存至 redis - search_cache() 方法

只有在新闻被管理员审批通过的时候,新闻才可以缓存到 redis 里面。
管理员在 “审批新闻” 的时候是可以获得到 “被审批通过的新闻” 的 id,所以可以通过 “新闻id” 去数据库里查询要缓存到 “redis” 里面的数据。
重点新增了 "查找缓存记录 " - 第 188 行 - 第 213 行
 

# coding:utf-8


from db.mysql_db import pool


"""
定义 NewsDao 类
"""
class NewsDao:
    """
    查询待审批新闻列表
    1、定义 search_unreview_list 方法,传入参数 page
    2、针对 search_unreview_list  方法,进行异常捕获
    """
    def search_unreview_list(self, page):       # 定义 search_unreview_list;查询 "待审批" 新闻列表
        try:                                    # try 语句捕获异常
            con=pool.get_connection()           # 定义一个连接(从连接池取出一个连接)
            cursor=con.cursor()                 # 创建游标
            """
            1、将查询待审批新闻列表 SQL语句 赋值给 sql
            2、使用表连接将查询到的新闻记录进行 分页 ,每一页 10条记录;"新闻表、类型表、用户表"
            3、根据 creat_time 字段降序排列,也就是最新的新闻排在最上面
            """
            sql="SELECT n.id,n.title,t.type,u.username " \
                "FROM t_news n JOIN t_type t ON n.type_id=t.id " \
                "JOIN t_user u ON n.editor_id=u.id " \
                "WHERE n.state=%s " \
                "ORDER BY n.create_time DESC " \
                "LIMIT %s,%s"
            cursor.execute(sql, ("待审批", (page-1)*10, 10))     # 将 page 换算为起始位置 和偏移量
                                                                # 举例:显示第一页 --> page为1
                                                                # '(1-1)*10 ,10'为查询第0位开始,偏移10的记录,则就是前十条记录
                                                                # 同理:第二页记录从第 10 条记录开始,为 '(2-1)*10 ,10'
            result=cursor.fetchall()        # 将查询的结果集 赋值 给 result ; 获取全部结果集 使用 fetchall()方法。
            return result
        except Exception as e:
            print(e)
        finally:
            if "con" in dir():
                con.close()

    """
    查询 "待审批新闻" 的总页数
    1、定义 search_unreview_count_page 方法,不需要传入参数
    2、针对 search_unreview_count_page 方法,进行异常捕获
    """
    def search_unreview_count_page(self):
        try:
            con=pool.get_connection()
            cursor=con.cursor()
            """
            将 "查询待审批新闻"总数分页的 SQL语句 赋值给 sql
            """
            sql="SELECT CEIL(COUNT(*)/10) FROM t_news WHERE state=%s"       # CEIL() 函数是结果有小数位,强制进一位。
            cursor.execute(sql, ["待审批"])
            count_page=cursor.fetchone()[0]             # 查询结果集只有一条记录,所以这里使用 fetchone()
            return count_page
        except Exception as e:
            print(e)
        finally:
            if "con" in dir():
                con.close()

    """
    审批新闻
    1、定义 update_unreview_news() 方法,传入参数 id
    2、针对 update_unreview_news() 方法,进行异常捕获
    """
    def update_unreview_news(self, id):
        try:
            con = pool.get_connection()
            con.start_transaction()
            cursor = con.cursor()
            sql = "UPDATE t_news SET state=%s WHERE id=%s"      # 预编译 "待审批新闻" SQL语句,将其变更为 "已审批"
            cursor.execute(sql, ("已审批", id))
            con.commit()
        except Exception as e:
            if "con" in dir():
                con.rollback()
            print(e)
        finally:
            if "con" in dir():
                con.close()

    """
    查询新闻列表
    1、定义 search_list() 方法,传入参数 page , 查询全部 新闻记录 的SQL语句赋值给 sql
    2、针对 search_list() 方法,进行异常捕获。
    """
    def search_list(self, page):
        try:                                    # try 语句捕获异常
            con=pool.get_connection()           # 定义一个连接(从连接池取出一个连接)
            cursor=con.cursor()                 # 创建游标
            """
            1、将查询待审批新闻列表 SQL语句 赋值给 sql
            2、使用表连接将查询到的新闻记录进行 分页 ,每一页 10条记录;"新闻表、类型表、用户表"
            """
            sql="SELECT n.id,n.title,t.type,u.username " \
                "FROM t_news n JOIN t_type t ON n.type_id=t.id " \
                "JOIN t_user u ON n.editor_id=u.id " \
                "ORDER BY n.create_time DESC " \
                "LIMIT %s,%s"
            cursor.execute(sql, ((page-1)*10, 10))      # 将 page 换算为起始位置 和偏移量
                                                        # 举例:显示第一页 --> page为1
                                                        # '(1-1)*10 ,10'为查询第0位开始,偏移10的记录,则就是前十条记录
                                                        # 同理:第二页记录从第 10 条记录开始,为 '(2-1)*10 ,10'
            result=cursor.fetchall()        # 将查询的结果集 赋值 给 result ; 获取全部结果集 使用 fetchall()方法。
            return result
        except Exception as e:
            print(e)
        finally:
            if "con" in dir():
                con.close()

    """
    查询新闻总页数
    """
    def search_count_page(self):
        try:
            con=pool.get_connection()
            cursor=con.cursor()
            """
            将 "查询新闻总页数" SQL语句 赋值给 sql
            """
            sql="SELECT CEIL(COUNT(*)/10) FROM t_news"       # CEIL() 函数是结果有小数位,强制进一位。
            cursor.execute(sql)
            count_page=cursor.fetchone()[0]                  # 查询结果集只有一条记录,所以这里使用 fetchone()
            return count_page
        except Exception as e:
            print(e)
        finally:
            if "con" in dir():
                con.close()

    """
    删除新闻
    1、定义 delete_by_id() 方法,传入参数 id , 根据新闻主键 id 删除新闻记录的 SQL语句 赋值给 sql
    2、针对 delete_by_id() 方法,进行异常捕获。
    """
    def delete_by_id(self, id):
        try:
            con = pool.get_connection()
            con.start_transaction()
            cursor = con.cursor()
            sql = "DELETE FROM t_news WHERE id=%s"  # 预编译 "删除新闻" SQL语句
            cursor.execute(sql, [id])
            con.commit()
        except Exception as e:
            if "con" in dir():
                con.rollback()
            print(e)
        finally:
            if "con" in dir():
                con.close()

    """
    添加新闻
    1、定义 insert() 方法,传入 
        title[新闻标题], 
        editor_id[新闻作者id], 
        type_id[新闻类型], 
        content_id[新闻正文id], '正文' 是保存在 'MongoDB' 数据库的,目前我们还没有接触,当学完 MongoDB 知识点后,就可以使用了
        is_top[是否置顶|置顶级别]
    2、将传入的新闻的参数,赋值给添加新闻的 SQL 语句
    3、针对 insert() 方法,进行异常捕获。
    """
    def insert(self, title, editor_id, type_id, content_id, is_top):
        try:
            con = pool.get_connection()
            con.start_transaction()     # 开启事务
            cursor=con.cursor()         # 打开游标

            """添加新闻的SQL语句 [通过格式化字符串将传入的参数作为 SQL 的 VALUES,state 的值为 '待审批']"""
            sql="INSERT INTO t_news(title,editor_id,type_id,content_id,is_top,state) " \
                "VALUES(%s, %s, %s, %s, %s, %s)"
            cursor.execute(sql, (title, editor_id, type_id, content_id, is_top, "待审批"))
            con.commit()                # 提交事务
        except Exception as e:
            if "con" in dir():          # 回滚事务
                con.rollback()
            print(e)
        finally:
            if "con" in dir():          # 关闭事务
                con.close()


    """
    查找用于缓存的新闻记录
    1、定义 search_cache() 方法,传入新闻的  id
    2、将传入的新闻的参数,赋值给添加新闻的 SQL 语句
    3、针对 search_cache() 方法,进行异常捕获。
    """
    def search_cache(self, id):
        try:
            con=pool.get_connection()
            cursor=con.cursor()

            """查询新闻记录的 SQL 语句,使用表连接关联查询实现; 通过用户的 id 查询到用户的 username ,将其存入 redis """
            sql="SELECT n.title,u.username,t.type,n.content_id," \
                "n.is_top,n.create_time " \
                "FROM t_news n " \
                "JOIN t_type t ON n.type_id=t.id " \
                "JOIN t_user u ON n.editor_id=u.id " \
                "WHERE n.id=%s"
            cursor.execute(sql, [id])       # 传入参数 id
            result=cursor.fetchone()        # 查询结果集只有一条记录,所以这里使用 fetchone() ;赋值给 result
            return result
        except Exception as e:
            print(e)
        finally:
            if "con" in dir():
                con.close()

 实现新闻缓存功能 - “news_service.py” - 从数据库提取明确的新闻数据保存至 redis - search_cache() 方法

  • 封装 “news_service.py” ,代码内容如下:
  • 重点新增了 “添加新闻” - 第 67 行 - 第 73 行
  • # coding:utf-8
    
    
    from db.news_dao import NewsDao
    
    
    """
    定义 NewsService 类
    """
    class NewsService:
        __new_dao = NewsDao()       # 实例化 NewsDao ,赋值给私有变量 __new_dao
    
        """
        1、查询待审批新闻列表;定义 search_unreview_list 方法,传入参数 page
        2、调用 __new_dao 实例 的 search_unreview_list 方法,赋值给 "result",并返回结果
        """
        def search_unreview_list(self, page):
            result = self.__new_dao.search_unreview_list(page)
            return result
    
        """
        1、查询 "待审批新闻" 的总页数;定义 search_unreview_count_page 方法,不需要传入参数
        2、调用 __new_dao 实例 的 search_unreview_count_page 方法,赋值给 "count_page",并返回结果
        """
        def search_unreview_count_page(self):
            count_page = self.__new_dao.search_unreview_count_page()
            return count_page
    
        """
        1、审批新闻;定义 update_unreview_news() 方法,传入参数 id。
        2、调用 __new_dao 实例 的 update_unreview_news() 方法
        """
        def update_unreview_news(self, id):
            self.__new_dao.update_unreview_news(id)
    
        """
        1、查询新闻列表;定义 search_list() 方法,传入参数 apge
        2、调用 __new_dao 实例 的 update_unreview_news() 方法
        """
        def search_list(self, page):
            result = self.__new_dao.search_list(page)
            return result
    
        """
        查询新闻总页数
        """
        def search_count_page(self):
            count_page = self.__new_dao.search_count_page()
            return count_page
    
        """
        删除新闻
        1、定义 delete_by_id() 方法,传入参数 id ,
        2、调用 __new_dao 实例的 delete_by_id() 方法
        """
        def delete_by_id(self, id):
            self.__new_dao.delete_by_id(id)
    
        """
        添加新闻
        1、定义 insert() 方法,传入 title, editor_id, type_id, content_id, is_top
        2、调用 __new_dao 实例的 insert() 方法
        """
        def insert(self, title, editor_id, type_id, content_id, is_top):
            self.__new_dao.insert(title, editor_id, type_id, content_id, is_top)
    
        """
        查找用于缓存的新闻记录
        1、定义 search_cache() 方法,传入 id
        """
        def search_cache(self, id):
            result = self.__new_dao.search_cache(id)
            return result
    

     实现保存缓存新闻功能 - “redis_news_dao.py” 将 “审批通过的新闻” 缓存到 redis 的类 -RedisNewsDao

  • 在 “db” 包中创建 “redis_news_dao.py” 模块,编写代码如下:
  •  

    # coding:utf-8
    
    
    import redis                            # 导入 redis 模块
    from db.redis_db import redis_Pool      # 导入 redis 连接池
    
    
    """
    定义 RedisNewsDao 类
    """
    class RedisNewsDao:
    
        """
        1、创建 insert() 方法,向 redis 中缓存 "审批通过" 的新闻的参数
        2、传入参数 id [新闻id], title [新闻标题], username [新闻作者], type [新闻类型], content [新闻内容], is_top [是否置顶], create_time [创建时间]
        3、针对 insert() 方法,进行异常捕获。
        """
        def insert(self, id, title, username, type, content, is_top, create_time):
            """构建连接"""
            con=redis.Redis(
                connection_pool=redis_Pool
            )
    
            """异常的捕获"""
            try:
                con.hmset(id, {
                    "title": title,
                    "author": username,
                    "type": type,
                    "content": content,
                    "is_top": is_top,
                    "create_time": create_time
                })
    
                """
                设置新闻置顶时间
                1、如果 is_top 的值为 0 ,则该新闻只置顶 24 小时
                2、非 0 状态的情况下,则一直置顶
                """
                if is_top==0:
                    con.expire(id, 24*60*60)
            except Exception as e:      # 打印输出异常
                print(e)
            finally:                    # 回收连接
                del con
    

    实现保存缓存新闻功能 - “news_service.py” - 将 “审批通过的新闻” 缓存到 redis - cache_news()

  • 需要将 RedisNewsDao 导入,还需要实例化 RedisNewsDao 。
  • 重点新增了 “添加新闻” - 第 5 行 、第 13 行 、第 79 行 - 第 85 行
  •  

    # coding:utf-8
    
    
    from db.news_dao import NewsDao
    from db.redis_news_dao import RedisNewsDao
    
    
    """
    定义 NewsService 类
    """
    class NewsService:
        __new_dao = NewsDao()               # 实例化 NewsDao ,赋值给私有变量 __new_dao
        __redis_news_dao = RedisNewsDao()   # 实例化 RedisNewsDao ,赋值给私有变量 __redis_news_dao
    
        """
        1、查询待审批新闻列表;定义 search_unreview_list 方法,传入参数 page
        2、调用 __new_dao 实例 的 search_unreview_list 方法,赋值给 "result",并返回结果
        """
        def search_unreview_list(self, page):
            result = self.__new_dao.search_unreview_list(page)
            return result
    
        """
        1、查询 "待审批新闻" 的总页数;定义 search_unreview_count_page 方法,不需要传入参数
        2、调用 __new_dao 实例 的 search_unreview_count_page 方法,赋值给 "count_page",并返回结果
        """
        def search_unreview_count_page(self):
            count_page = self.__new_dao.search_unreview_count_page()
            return count_page
    
        """
        1、审批新闻;定义 update_unreview_news() 方法,传入参数 id。
        2、调用 __new_dao 实例 的 update_unreview_news() 方法
        """
        def update_unreview_news(self, id):
            self.__new_dao.update_unreview_news(id)
    
        """
        1、查询新闻列表;定义 search_list() 方法,传入参数 apge
        2、调用 __new_dao 实例 的 update_unreview_news() 方法
        """
        def search_list(self, page):
            result = self.__new_dao.search_list(page)
            return result
    
        """
        查询新闻总页数
        """
        def search_count_page(self):
            count_page = self.__new_dao.search_count_page()
            return count_page
    
        """
        删除新闻
        1、定义 delete_by_id() 方法,传入参数 id ,
        2、调用 __new_dao 实例的 delete_by_id() 方法
        """
        def delete_by_id(self, id):
            self.__new_dao.delete_by_id(id)
    
        """
        添加新闻
        1、定义 insert() 方法,传入 title, editor_id, type_id, content_id, is_top
        2、调用 __new_dao 实例的 insert() 方法
        """
        def insert(self, title, editor_id, type_id, content_id, is_top):
            self.__new_dao.insert(title, editor_id, type_id, content_id, is_top)
    
        """
        查找用于缓存的新闻记录
        1、定义 search_cache() 方法,传入 id,通过 id 查找新闻
        2、调用 __new_dao 实例的 search_cache() 方法
        3、返回新闻记录
        """
        def search_cache(self, id):
            result = self.__new_dao.search_cache(id)
            return result
    
        """
        将需要缓存的新闻保存至redis
        1、定义 cache_news() 方法,并传入需要缓存的新闻的数据,传入 id, titile, username, type, content, is_top, create_time
        2、调用 __redis_news_dao 实例的 insert() 方法
        """
        def cache_news(self, id, titile, username, type, content, is_top, create_time):
            self.__redis_news_dao.insert(id, titile, username, type, content, is_top, create_time)
    

     实现新闻缓存功能 - “app.py” - 修改 “审批新闻” - 提取缓存数据

  • 找到 “app.py” 这个模块的调用 __news_service.update_unreview_news(news_id) 的位置,也就是 第 153 行 。
    这里是调用的 new_service 的 update_unreview_news 函数,通过传入的 news_id 获取要被缓存的新闻数据。
    这一行代码实现的功能是,将 “审批通过的新闻” 修改了一下状态,即为 “审批通过” 。
    以上是之前我们实现的功能与效果;
    现在不仅仅是要修改 “审批通过” 的状态,我们还要读取 “审批通过” 的新闻的缓存数据。
    所以我们将要在 第 153 行 的后面开始获取 "被缓存的新闻" 的数据,然后再将这些数据通过 __news_service.cache_news() 缓存至 redis
     

    # coding:utf-8
    
    
    from colorama import Fore, Style
    from getpass import getpass     # 该模块的作用是遮挡输入的密码
    from service.user_service import UserService
    from service.news_service import NewsService
    from service.role_service import RoleService
    from service.type_service import TypeService
    import os                       # os 模块的作用是利用 "clear" 系统命令(win电脑 - "cls"),清空控制台的内容
    import sys                      # sys 模块的作用主要是利用 "exit()" 方法进行安全退出;(释放数据库连接、文件连接...之后退出)
    import time
    
    
    __user_service = UserService()      # 实例化 UserService() 对象,赋值给私有变量 "__user_service"
    __news_service = NewsService()
    __role_service = RoleService()
    __type_service = TypeService()
    
    while 1:
        os.system("clear")      # 清空控制台
        print(Fore.LIGHTBLUE_EX, "\n\t=========================")       # "\n":换行 ;"\t":table,四个空格。
        print(Fore.LIGHTBLUE_EX, "\n\t欢迎使用新闻管理系统")
        print(Fore.LIGHTBLUE_EX, "\n\t=========================")
        print(Fore.LIGHTGREEN_EX, "\n\t1.登录系统")
        print(Fore.LIGHTGREEN_EX, "\n\t2.退出系统")
        print(Style.RESET_ALL)                     # 重置字体的颜色
        # opt = input("\n\t请输入操作编号:")           # 将用户输入的内容 赋值给变量 opt
        opt=input("\n\t输入操作编号:")
        """
        对用户输入的交互内容进行校验
        1、输入 "1" ,进入 "登录系统"
        2、输入 "2" ,则退出系统
        """
        if opt=="1":                               # 当用户输入 1,进行 登录系统
            username = input("\n\t用户名:")
            password = getpass("\n\t密码:")        # 使用 getpass() 可以将输入的密码 隐去
            result = __user_service.login(username, password)       # 调用 __user_service 的 login 方法,实现登录;赋值给 result
    
            """
            针对登录成功用户进行身份校验
            1、为 True ,判断 登录用户 的身份,根据对应的身份,进入对应的身份层级的轮询
            2、为 False ,则 登录失败,返回 登录 层级的轮询
            """
            if result == True:
                role = __user_service.search_user_role(username)    # 调用 __user_service 的 search_user_role 方法,校验用户身份
                os.system("clear")
    
                """
                判断登陆成功后的身份;"新闻编辑" 与 "管理员" 分别跳转各自对应的菜单层级 
                """
                while 1:
                    os.system("clear")  # 清空终端信息
                    if role == "新闻编辑":
                        print(Fore.LIGHTGREEN_EX, "\n\t1.发表新闻")
                        print(Fore.LIGHTGREEN_EX, "\n\t2.编辑新闻")
                        print(Fore.LIGHTRED_EX, "\n\tback.退出登录")
                        print(Fore.LIGHTRED_EX, "\n\texit.退出系统 ")
                        print(Style.RESET_ALL)
                        opt = input("\n\t请输入操作编号:")
    
                        """[发表新闻] 需求的实现"""
                        if opt=="1":
                            os.system("clear")
                            title=input("\n\t新闻标题:")                        # 定义新闻标题
                            userid=__user_service.search_userid(username)      # 查询用户 id
                            result=__type_service.search_list()                # 获得所有新闻类型
    
                            """利用 for 循环获取所有的新闻类型"""
                            for index in range(len(result)):
                                one = result[index]
                                print(Fore.LIGHTBLUE_EX, "\n\t%d.%s" % (index + 1, one[1]))
                            print(Style.RESET_ALL)
                            opt = input("\n\t类型编号:")
                            type_id = result[int(opt) - 1][0]
                            #TODO 新闻正文内容;正文牵扯到 MongoDB 数据库,这里先备注个 TODO,也顺便先将 content_id 的值固定为 100
                            content_id=100
                            is_top=input("\n\t置顶级别(0-5):")          # 设置置顶级别
                            is_commite=input("\n\t是否提交(Y/N):")      # 询问是否保存
                            if is_commite=="Y" or is_commite=="y":     # 判断用户的输入
                                __news_service.insert(title, userid, type_id, content_id, is_top)      # 传入参数
                                print("\n\t保存成功(3秒自动返回)")
                                time.sleep(3)
    
                    elif role == "管理员":
                        print(Fore.LIGHTGREEN_EX, "\n\t1.新闻管理")
                        print(Fore.LIGHTGREEN_EX, "\n\t2.用户管理")
                        print(Fore.LIGHTRED_EX, "\n\tback.退出登录")
                        print(Fore.LIGHTRED_EX, "\n\texit.退出系统 ")
                        print(Style.RESET_ALL)
                        opt = input("\n\t请输入操作编号:")
    
                        """
                        根据登录用户键入的选项,执行对应的操作
                        """
                        if opt == "1":
                            """
                            选项 1 :进入 "新闻管理" 三级菜单(轮询)
                            """
                            while 1:
                                os.system("clear")        # 清空终端信息
                                print(Fore.LIGHTGREEN_EX, "\n\t1.审批新闻")         #
                                print(Fore.LIGHTGREEN_EX, "\n\t2.删除新闻")
                                print(Fore.LIGHTRED_EX, "\n\tback.返回上一层")
                                print(Style.RESET_ALL)
                                opt = input("\n\t输入操作编号:")          # 根据输入的选项,执行对应的操作
                                if opt=="1":
                                    """
                                    选项 1 :进入 "审批新闻" 四级菜单(轮询)
                                    """
                                    page=1      # 定义 page 变量,保存当前是 "第1页"
                                                # page 这个变量不能定义在 while 循环内,定义在 while 内,每一次轮询都会重置 page
                                    while 1:
                                        os.system("clear")    # 清空终端
                                        """
                                        1、需要导入 service包 news_service模块 NewsService类,将其赋值给 私有变量 ---> __news_service 
                                        2、__news_service 私有变量 参考 第 14 行代码
                                        """
                                        count_page=__news_service.search_unreview_count_page()  # 调用查询"待审批新闻"总页数的方法
                                        result=__news_service.search_unreview_list(page)        # 将第1页的结果集赋值给 result
    
                                        """
                                        将结果集通过索引的形式进行一个 for 循环输出
                                        """
                                        for index in range(len(result)):
                                            one=result[index]
                                            print(Fore.LIGHTBLUE_EX, "\n\t%d\t%s\t%s\t%s" %(index+1, one[1], one[2], one[3]))
                                        print(Fore.LIGHTBLUE_EX, "\n\t-------------------")
                                        print(Fore.LIGHTBLUE_EX, "\n\t%d/%d" %(page, count_page))
                                        print(Fore.LIGHTBLUE_EX, "\n\t-------------------")
                                        print(Fore.LIGHTRED_EX, "\n\tback.返回上一层")
                                        print(Fore.LIGHTRED_EX, "\n\tprev.上一页")
                                        print(Fore.LIGHTRED_EX, "\n\tnext.下一页")
                                        print(Style.RESET_ALL)
                                        opt = input("\n\t输入操作编号:")
                                        """
                                        针对用户的输入进行 判断;
                                        """
                                        if opt=="back":     # 返回上一层
                                            break
                                        elif opt=="prev" and page>1:    # 向 "上一页" 翻页,前置条件不能为 "第一页"
                                            page-=1
                                        elif opt=="next" and page<count_page:   # 向 "下一页" 翻页,前置条件不能为 "最后一页"
                                            page+=1
                                        elif int(opt) >= 1 and int(opt) <= 10:
                                            """ 
                                            1、这里的 opt 获取到输入的编号是 string 类型,需要先转成 int 类型
                                            2、因为每一页的新闻数量是十条,所以输入的取值范围是 大于等于1、小于等于10
                                            3、在获取输入的记录时,这里获取的新闻的id并不是数据库中新闻记录的主键id
                                            4、传入的记录其实是显示在终端的待审批新闻的索引,所以我们需要将传入的记录换算为 "待审批新闻" 的索引位
                                            """
                                            news_id = result[int(opt) - 1][0]
                                            __news_service.update_unreview_news(news_id)
                                            result=__news_service.search_cache(news_id)     # 先获取将要 "被缓存的新闻" 的结果
    
                                            """将新闻的数据,按照顺序依次取出。"""
                                            title=result[0]             # 新闻标题
                                            username=result[1]          # 新闻作者
                                            type=result[2]              # 新闻类型
                                            # TODO 查找新闻正文
                                            """MySQL获取的 content_id ,通过 content_id 在MongoDB查找新闻正文,后续完善~"""
                                            content_id=result[3]
                                            content='100'               # 当前填充数据,随意给一个 100 演示的值即可
                                            is_top=result[4]            # 是否置顶
                                            create_time=str(result[5])  # 创建时间;直接获取的是 '时间类型' ,存储到 redis 中,需要变更数据类型
    
                                            """调用 __news_service 封装好的 cache_news() 函数"""
                                            __news_service.cache_news(news_id, title, username, type, content, is_top, create_time)
    
                                elif opt=="2":
                                    """
                                      选项 2 :进入 "删除新闻" 四级菜单(轮询)
                                    """
                                    page = 1  # 定义 page 变量,保存当前是 "第1页"
                                    # page 这个变量不能定义在 while 循环内,定义在 while 内,每一次轮询都会重置 page
                                    while 1:
                                        os.system("clear")  # 清空终端
                                        """
                                        1、需要导入 service包 news_service模块 NewsService类,将其赋值给 私有变量 ---> __news_service 
                                        2、__news_service 私有变量 参考 第 14 行代码
                                        """
                                        count_page = __news_service.search_count_page()  # 调用 "新闻总页数" 的方法
                                        result = __news_service.search_list(page)        # 将查询 "新闻列表" 的结果集赋值给 result
    
                                        """
                                        将结果集通过索引的形式进行一个 for 循环输出
                                        """
                                        for index in range(len(result)):
                                            one = result[index]
                                            print(Fore.LIGHTBLUE_EX,
                                                  "\n\t%d\t%s\t%s\t%s" % (index + 1, one[1], one[2], one[3]))
                                        print(Fore.LIGHTBLUE_EX, "\n\t-------------------")
                                        print(Fore.LIGHTBLUE_EX, "\n\t%d/%d" % (page, count_page))
                                        print(Fore.LIGHTBLUE_EX, "\n\t-------------------")
                                        print(Fore.LIGHTRED_EX, "\n\tback.返回上一层")
                                        print(Fore.LIGHTRED_EX, "\n\tprev.上一页")
                                        print(Fore.LIGHTRED_EX, "\n\tnext.下一页")
                                        print(Style.RESET_ALL)
                                        opt = input("\n\t输入操作编号:")
                                        """
                                        针对用户的输入进行 判断;
                                        """
                                        if opt == "back":  # 返回上一层
                                            break
                                        elif opt == "prev" and page > 1:  # 向 "上一页" 翻页,前置条件不能为 "第一页"
                                            page -= 1
                                        elif opt == "next" and page < count_page:  # 向 "下一页" 翻页,前置条件不能为 "最后一页"
                                            page += 1
                                        elif int(opt) >= 1 and int(opt) <= 10:
                                            """ 
                                            1、这里的 opt 获取到输入的编号是 string 类型,需要先转成 int 类型
                                            2、因为每一页的新闻数量是十条,所以输入的取值范围是 大于等于1、小于等于10
                                            3、在获取输入的记录时,这里获取的新闻的id并不是数据库中新闻记录的主键id
                                            4、传入的记录其实是显示在终端的新闻记录的索引,所以我们需要将传入的记录换算为 "新闻记录" 的索引位
                                            """
                                            news_id = result[int(opt)-1][0]
                                            __news_service.delete_by_id(news_id)
                                elif opt == "back":
                                    break
                        elif opt == "2":
                            """
                            选项 2 :进入 "用户管理" 三级菜单(轮询)
                            """
                            while True:
                                os.system("clear")
                                print(Fore.LIGHTGREEN_EX, "\n\t1.添加用户")
                                print(Fore.LIGHTGREEN_EX, "\n\t2.修改用户")
                                print(Fore.LIGHTGREEN_EX, "\n\t3.删除用户")
                                print(Fore.LIGHTRED_EX, "\n\tback.返回上一层")
                                print(Style.RESET_ALL)
                                opt = input("\n\t输入操作编号:")
                                if opt=="back":
                                    break
                                elif opt=="1":
                                    """
                                    选项 1 :进入 "添加用户" 四级菜单(轮询)
                                    """
                                    os.system("clear")
                                    username=input("\n\t用户名:")
                                    password = getpass("\n\t密码:")        # getpass() 遮挡输入的密码
                                    repassword=getpass("\n\t重复密码:")     # 密码需要输入两次,且需要针对两次密码进行相等判断
                                    if password!=repassword:              # 两次密码不一致,进入下一次的轮询
                                        print("\n\t两次密码不一致(3秒自动返回)")
                                        time.sleep(3)
                                        continue
                                    email=input("\n\t邮箱:")
                                    result=__role_service.search_list()     # 向控制台输出已有的角色列表
                                                                            # 此处需要导入 service包 role_service模块 的 RoleService类
                                                                            # 参考 第 8 行 与 第 16 行 代码
                                    for index in range(len(result)):        # 循环输出 "角色列表" 的结果集
                                        one=result[index]
                                        print(Fore.LIGHTBLUE_EX, "\n\t%d.%s" %(index+1, one[1]))
                                    print(Style.RESET_ALL)
                                    opt=input("\n\t角色编号:")          # 根据输入的内容,将其换算为 "角色编号"
                                    role_id=result[int(opt)-1][0]
                                    __user_service.insert(username, password, email, role_id)
                                    print("\n\t保存成功(3秒自动返回)")
                                    time.sleep(3)
                                elif opt=="2":
                                    page = 1
                                    while True:
                                        os.system("clear")
                                        count_page = __user_service.search_count_page()
                                        result = __user_service.search_list(page)
                                        for index in range(len(result)):
                                            one = result[index]
                                            print(Fore.LIGHTBLUE_EX,
                                                  "\n\t%d\t%s\t%s" % (index + 1, one[1], one[2]))
                                        print(Fore.LIGHTBLUE_EX, "\n\t-------------------")
                                        print(Fore.LIGHTBLUE_EX, "\n\t%d/%d" % (page, count_page))
                                        print(Fore.LIGHTBLUE_EX, "\n\t-------------------")
                                        print(Fore.LIGHTRED_EX, "\n\tback.返回上一层")
                                        print(Fore.LIGHTRED_EX, "\n\tprev.上一页")
                                        print(Fore.LIGHTRED_EX, "\n\tnext.下一页")
                                        print(Style.RESET_ALL)
                                        opt = input("\n\t输入操作编号:")
                                        if opt == "back":
                                            break
                                        elif opt == "prev" and page > 1:
                                            page -= 1
                                        elif opt == "next" and page < count_page:
                                            page += 1
                                        elif int(opt) >= 1 and int(opt) <= 10:
                                            """ 
                                            1、这里的 opt 获取到输入的编号是 string 类型,需要先转成 int 类型
                                            2、因为每一页的用户数量是十条,所以输入的取值范围是 大于等于1、小于等于10
                                            3、在获取输入的记录时,这里获取的用户的id并不是数据库中新闻记录的主键id
                                            4、传入的记录其实是显示在终端的用户记录的索引,所以我们需要将传入的记录换算为 "用户记录" 的索引位
                                            """
                                            os.system("clear")
                                            user_id=result[int(opt)-1][0]       # 获取终端显示的用户记录索引对应的用户id
                                            username = input("\n\t新用户名:")
                                            password = getpass("\n\t新密码:")
                                            repassword = getpass("\n\t再次输入密码:")
                                            if password!=repassword:
                                                print(Fore.LIGHTRED_EX, "\n\t两次密码不一致(3秒自动返回)")
                                                print(Style.RESET_ALL)
                                                time.sleep(3)
                                                break
                                            email = input("\n\t新邮箱:")
                                            result = __role_service.search_list()
                                            for index in range(len(result)):        # 循环输出 "角色列表" 的结果集
                                                one = result[index]
                                                print(Fore.LIGHTBLUE_EX, "\n\t%d.%s" % (index + 1, one[1]))
                                            print(Style.RESET_ALL)
                                            opt = input("\n\t角色编号:")
                                            role_id = result[int(opt) - 1][0]
                                            opt=input("\n\t是否保存(Y/N)")
                                            if opt=="Y" or opt=="y":
                                                __user_service.update(user_id, username, password, email, role_id)
                                                print("\n\t保存成功(3秒自动返回)")
                                                time.sleep(3)
                                elif opt=="3":
                                    page = 1
                                    while True:
                                        os.system("clear")
                                        count_page = __user_service.search_count_page()
                                        result = __user_service.search_list(page)
                                        for index in range(len(result)):
                                            one = result[index]
                                            print(Fore.LIGHTBLUE_EX,
                                                  "\n\t%d\t%s\t%s" % (index + 1, one[1], one[2]))
                                        print(Fore.LIGHTBLUE_EX, "\n\t-------------------")
                                        print(Fore.LIGHTBLUE_EX, "\n\t%d/%d" % (page, count_page))
                                        print(Fore.LIGHTBLUE_EX, "\n\t-------------------")
                                        print(Fore.LIGHTRED_EX, "\n\tback.返回上一层")
                                        print(Fore.LIGHTRED_EX, "\n\tprev.上一页")
                                        print(Fore.LIGHTRED_EX, "\n\tnext.下一页")
                                        print(Style.RESET_ALL)
                                        opt = input("\n\t输入操作编号:")
                                        if opt == "back":
                                            break
                                        elif opt == "prev" and page > 1:
                                            page -= 1
                                        elif opt == "next" and page < count_page:
                                            page += 1
                                        elif int(opt) >= 1 and int(opt) <= 10:
                                            """ 
                                            1、这里的 opt 获取到输入的编号是 string 类型,需要先转成 int 类型
                                            2、因为每一页的用户数量是十条,所以输入的取值范围是 大于等于1、小于等于10
                                            3、在获取输入的记录时,这里获取的用户的id并不是数据库中新闻记录的主键id
                                            4、传入的记录其实是显示在终端的用户记录的索引,所以我们需要将传入的记录换算为 "用户记录" 的索引位
                                            """
                                            os.system("clear")
                                            user_id=result[int(opt)-1][0]
                                            __user_service.delete_by_id(user_id)
                                            print("\n\t删除成功(3秒自动返回)")
                                            time.sleep(3)
                        elif opt == "back":         # 返回上一级层级菜单
                            break
                        elif opt == "exit":         # 安全退出
                            sys.exit(0)
            else:
                print("\n\t*****登录失败...3秒后自动返回!*****")
                time.sleep(3)
        elif opt=="2":
            sys.exit(0)     # 安全退出 ---> 利用 "exit()" 方法安全退出;(释放数据库连接、文件连接...之后退出)
    

     

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

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

相关文章

Allegro如何用Label Tune功能自动调整丝印到器件中心

Allegro如何用Label Tune功能自动调整丝印到器件中心 在做PCB设计的时候,调整丝印是比较费时的工作,如果需要把整板的丝印位号调整到器件的中心做装配图使用,Allegro的Label Tune功能支持快速把丝印位号居中到器件中心。 以下图为例,快速把所有丝印位号居中 调整前 调整后…

若依框架 --- 偶发的el-select无法选择的问题

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是小童&#xff0c;Java开发工程师&#xff0c;CSDN博客博主&#xff0c;Java领域新星创作者 &#x1f4d5;系列专栏&#xff1a;前端、Java、Java中间件大全、微信小程序、微信支付、若依框架、Spring全家桶 &#x1f4…

RBCD深度利用之“烂番茄”

1.RBCD简介 本篇文章是在基于资源的约束委派的基础上的一个利用&#xff0c;篇幅会比较短&#xff0c;但个人认为利用面还是挺广泛的。于是就写一下。 首先&#xff0c;需要了解的是RBCD的基础知识&#xff1a; 简单回顾一下&#xff1a; 基于资源的约束委派(RBCD) 只支持2…

微电网两阶段鲁棒优化经济调度方法[3]【升级优化版本】(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️❤️&#x1f4a5;&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑…

【论文速递】NAACL2022-DEGREE: 一种基于生成的数据高效事件抽取模型

【论文速递】NAACL2022-DEGREE: 一种基于生成的数据高效事件抽取模型 【论文原文】&#xff1a;DEGREE A Data-Efficient Generation-Based Event Extraction Mode 【作者信息】&#xff1a;I-Hung Hsu &#xff0c; Kuan-Hao Huang&#xff0c; Elizabeth Boschee &#xff…

【总结】1591- 从入门到精通:使用 TypeScript 开发超强的 CLI 工具

作为一名开发者&#xff0c;掌握 CLI 工具的开发能力是非常重要的。本文将指导你如何使用 TypeScript 和 CAC 库开发出功能强大的 CLI 工具。快速入门首先&#xff0c;需要先安装 Node.js 和 npm&#xff08;Node Package Manager&#xff09;&#xff0c;然后在项目目录中创建…

【正点原子FPGA连载】第七章程序固化实验摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南

第七章程序固化实验 在前面的几个实验中&#xff0c;我们都是通过JTAG接口将FPGA配置文件和应用程序下载到MPSOC器件中。接下来我们将尝试把程序存储在非易失性存储器中&#xff0c;在上电或者复位时让程序自动运行&#xff0c;这个过程需要启动引导程序&#xff08;Boot Load…

【STM32笔记】HAL库UART串口配置及重定向(解决接收中断与scanf不能同时工作的问题)

【STM32笔记】HAL库UART串口配置及重定向&#xff08;解决接收中断与scanf不能同时工作的问题&#xff09; 首先 要使用printf和scanf 必不可少的就是 #include <stdio.h>这里需要做的就是配置单片机的UART 并且使其能够被printf和scanf调用 打开异步工作模式 并且选择…

openGauss单机版升级示例(2.0.1—>3.1.1)

文章目录前言一、升级前的准备工作二、升级主要步骤1、查看当前数据库版本2、创建临时目录用于存放安装文件3、下载最新需要升级的版本并解压4、执行前置脚本 openGauss的 gs_preinstall5、执行升级操作6、升级检查7、提交升级&#xff1a;三、附本期小知识前言 数据库版本升级…

你的自动化框架如何设计的?为什么感觉面试官总是不满意,到底问题出在哪?

前言去面试自动化测试岗位&#xff0c;尤其是接口自动化岗位&#xff0c;面试官总会问&#xff1a;说下你的自动化框架如何设计的&#xff1f;为什么回答后&#xff0c;面试官对你的框架设计总是感觉不满意&#xff1f;自动化测试实现的几种方式对于不同的公司来说&#xff0c;…

iOS16灵动岛横屏视频播放适配(ZFPlayer)

项目场景&#xff1a; 手机为iphone14Pro 版本iOS16.0.3 Xcode版本14.2 视频播放第三方库ZFPlayer 问题描述 使用视频时&#xff0c;视频播放自动横屏控制层的返回按钮和暂停按钮都点不到&#xff0c;上图错误、下图正确&#xff08;控制按钮距离屏幕左右减小50、视频全屏不做…

Maven:基础知识

Maven概念图生命周期目录工程创建测试常用命令COMPILATION ERROR : 不再支持目标选项 5。请使用 7 或更高版本。问题解决pom.xml文件properties配置示例scope配置详解概念图 依赖管理构建项目Maven 的底层核心实现项目的构建和管理必须通过插件完成&#xff0c;但插件本身并不包…

VC++打开或关闭目标进程的声音(扬声器)(附源码)

VC常用功能开发汇总&#xff08;专栏文章列表&#xff0c;欢迎订阅&#xff0c;持续更新...&#xff09;https://blog.csdn.net/chenlycly/article/details/124272585C软件异常排查从入门到精通系列教程&#xff08;专栏文章列表&#xff0c;欢迎订阅&#xff0c;持续更新...&a…

一刷代码随想录——单调栈

每日温度739题目描述&#xff1a;给定一个整数数组 temperatures &#xff0c;表示每天的温度&#xff0c;返回一个数组 answer &#xff0c;其中 answer[i] 是指对于第 i 天&#xff0c;下一个更高温度出现在几天后。如果气温在这之后都不会升高&#xff0c;请在该位置用 0 来…

spring security 核心类 和请求登陆过程

核心类图2. 执行登陆 首先请求被拦截器 UsernamePasswordAuthenticationFilter 拦截 看源代码可以看出默认拦截的是 /login 请求地址 当然这个地址是可以被配置的 private static final AntPathRequestMatcher DEFAULT_ANT_PATH_REQUEST_MATCHER new AntPathRequestMatche…

DFS深度优先算法 —— AcWing 842. 排列数字AcWing 843. n-皇后问题

一、了解dfs1、DFS&#xff08;Depth First Search&#xff09;DFS在我看来就是一条路走到黑&#xff0c;直到无路可走的情况下&#xff0c;才会选择回头&#xff0c;然后重新选择一条路&#xff08;官方说法即“优先考虑深度”&#xff09;整个进程反复进行直到所有节点都被访…

Allegro如何添加ICT操作指导

Allegro如何添加ICT操作指导 当PCB板需要做飞针测试的时候,通常需要在PCB设计的时候给需要测试的网络添加上ICT。 如图: Allegro支持给网络添加ICT,具体操作如下 首先在库中创建一个阻焊开窗的过孔,比如via10-ict一般阻焊开窗的尺寸比盘单边大2mil 在PCB中选择Manufacture…

Linux基础命令1(常见的系统进程、状态命令)

目录 Linux命令格式 Linux快捷按键 常用系统命令 man 查看命令的帮助信息 echo 输出信息&#xff08;将信息输出到屏幕上面&#xff09; date 查看系统的日期、时间 timedatectl 设置系统时间&#xff0c;主要是时区&…

程序环境--翻译+执行

ANSI C标准下&#xff0c;有两种程序环境。 第1种是翻译环境&#xff0c;在这个环境中源代码被转换为可执行的机器指令。 翻译环境包括&#xff1a;预处理&#xff08;预编译&#xff09;编译汇编链接。四个步骤。 第2种是执行/运行环境&#xff0c;它用于实际执行代码。 链接…

UPC-2023新生个人训练赛第18场-Rank1

问题 B: 2的N次方 题目描述 输入n行&#xff0c;每行一个整数x&#xff0c;输出2的x次方的个位是多少&#xff1f;2的3次方表示3个2相乘&#xff0c;结果是8 输入 输入n行&#xff0c;每行一个整数x 输出 输出n行&#xff0c;每行一个整数&#xff0c;2的x次方的个位。 …