实现新闻缓存功能 - “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()" 方法安全退出;(释放数据库连接、文件连接...之后退出)