基于 PyCharm 和 Navicat 的新闻管理系统
# 用于创建连接池
pip3 install mysql-connector-python
# 改变终端打印颜色
pip3 install colorama
1.创建连接池
文件地址:db/mysql_db.py
首先建立一个与 MySQL 数据库的连接池,以便在应用程序中复用连接,提高性能。
如果连接池创建失败,它会打印出异常信息,以便开发者了解错误原因并进行修复。
import mysql.connector.pooling
__config = {"host": "localhost","port": 3306,"user": "root","password": "888888","database": "cs_news"
}
try:pool = mysql.connector.pooling.MySQLConnectionPool(**__config,pool_size=10)
except Exception as e:print(e)
2.用户数据操作 UserDao
文件地址:db/user_dao.py
2.1 用户登录验证
Dao :操作用户数据表user_database access object
#利用面对对象的思维操作数据库 处理不匹配的问题 即抗拒不匹配
from db.mysql_db import pool
class UserDao:#验证用户登录def login(self, username, password):try:#操作数据库的连接项conn = pool.get_connection()#操作数据库的游标cursor = conn.cursor()# 编写sql语句,AES_DECRYPT()对称加密或解密函数,UNHEX()编码格式sql = "select count(*) from t_user where username = %s and AES_DECRYPT(UNHEX(password),'HelloWorld') = %s"#执行sqlcursor.execute(sql, (username, password))#获得结果集count = cursor.fetchone()[0]return True if count == 1 else Falseexcept Exception as e:print(e)finally:if "conn" in dir():conn.close()# 根据用户名查询用户角色def search_user_role(self,username):#构建异常结构,当执行错误时给予提示try:# 由于在方法中要执行sql语句,对数据库操作,因此需要从连接池中获得连接项conn = pool.get_connection()# 通过连接项获得游标对象cursor = conn.cursor()# 创建sql语句sql = "select r.role from t_user u join t_role r on u.role_id=r.id where u.username=%s"# 使用游标执行sqlcursor.execute(sql, [username])# 获得查询出的结果集role = cursor.fetchone()[0]# 返回结果据数据return roleexcept Exception as e:print(e)finally:if "conn" in dir():conn.close()
2.2 查询用户角色
from db.mysql_db import pool
class UserDao:def login(self, username, password): ...def search_user_role(self,username):#构建异常结构,当执行错误时给予提示try:# 由于在方法中要执行sql语句,对数据库操作,因此需要从连接池中获得连接项conn = pool.get_connection()# 通过连接项获得游标对象cursor = conn.cursor()# 创建sql语句sql = "select r.role from t_user u join t_role r on u.role_id=r.id where u.username=%s"# 使用游标执行sqlcursor.execute(sql, [username])# 获得查询出的结果集role = cursor.fetchone()[0]# 返回结果据数据return roleexcept Exception as e:print(e)finally:if "conn" in dir():conn.close()
3.用户业务逻辑处理 UserService
文件地址:service/user_service.py
定义一个名为 UserService
的类,它封装了用户相关的业务逻辑,如登录验证和查询用户角色。
# 该文件用于处理用户相关的业务,如登录、注册等
# 导入用户相关的dao
from db.user_dao import UserDao
#创建用户相关业务类
class UserService:# 获得UserDao对象,也称为UserDao对象实例化__user_dao = UserDao()# 登录验证业务def login(self, username, password):result = self.__user_dao.login(username, password)return result# 查询用户角色业务def search_user_role(self, username):role = self.__user_dao.search_user_role(username)return role
4.新闻数据操作 NewsDao
文件地址:db/news_dao.py
4.1 查询待审批的新闻
# 操作新闻数据表
# 导入连接池获得连接项
from db.mysql_db import pool
#创建操作新闻的类
class NewsDao:#查询待审批的新闻def search_unreview_list(self,page):# 创建异常try:# 获得连接项conn = pool.get_connection()# 获得游标cursor = conn.cursor()# 创建sqlsql = """SELECT n.id,n.title,t.type,u.username FROM t_news n join t_type t on n.type_id=t.idjoin t_user u on n.editor_id=u.idwhere n.state = %sORDER BY n.create_timeLIMIT %s,%s"""# 执行sqlcursor.execute(sql, ("待审批",(page-1)*5,5))# 获得查询结果result = cursor.fetchall()return result# 返回获得结果except Exception as e:print(e)finally:if "conn" in dir():conn.close()
# 测试功能方法
service = NewsDao()
result = service.search_unreview_list(4)
print(result)
4.2 查询待审批的新闻总页数
# 操作新闻数据表
# 导入连接池获得连接项
from db.mysql_db import pool
#创建操作新闻的类
class NewsDao:# 查询待审批的新闻def search_unreview_list(self,page): ...# 查询待审批的新闻总页数def search_unreview_count_page(self):try:#获得连接项conn = pool.get_connection()#获得游标cursor = conn.cursor()#创建sqlsql = "select ceil(count(*)/5) from t_news where state=%s"#执行sqlcursor.execute(sql,["待审批"])#获取结果集数据count_page = cursor.fetchone()[0]#返回数据return count_pageexcept Exception as e:print(e)finally:if "conn" in dir():conn.close()
# 测试功能方法
# service = NewsDao()
# result = service.search_unreview_list(4)
# print(result)
5.新闻业务逻辑处理类 NewsService
文件地址:service/news_service.py
# 导入新闻dao模块
from db.news_dao import NewsDao
# 创建新闻业务类
class NewsService:#实例化新闻Dao对象__news_dao = NewsDao()#查询待审批新闻列表def search_unreview_list(self,page):# 调用新闻Dao的对应函数result = self.__news_dao.search_unreview_list(page)# 返回数据return result#查询待审批新闻总页数def search_unreview_count_page(self):count_page = self.__news_dao.search_unreview_count_page()return count_page
6.新闻管理系统主控台 app_py
文件地址:app_py.py
# 该文件用于启动程序的controller控制文件
# 引入service包
from service.user_service import UserService
from service.news_service import NewsService
# 引入控制台变色
from colorama import Fore,Style
# 引入密码格式
from getpass import getpass
# 引入系统管理包
import os
# 引入控制台输入输出包
import sys
# 引入时间
import time
# 实例化用户业务对象
__user_service = UserService()
__news_service = NewsService()
while True:os.system("cls")# 清屏print(Fore.LIGHTRED_EX,"\n\t=================")print(Fore.LIGHTRED_EX, "\n\t欢迎使用新闻管理系统")print(Fore.LIGHTRED_EX, "\n\t=================")print(Fore.LIGHTYELLOW_EX, "\n\t1.登录系统")print(Fore.LIGHTYELLOW_EX, "\n\t2.退出系统")print(Style.RESET_ALL) #样式重置opt = input("\n\t输入操作编号") # 获取控制台输入的数据# 根据输入的数字判断业务方向if opt == "1":# 登录验证# 获得控制台输入的用户名密码username = input("\n\t用户名:")password = getpass("\n\t密码:")# 登录验证result = __user_service.login(username, password)# 判断登录验证返回结果if result == True:# 查询用户角色,根据用户角色适配功能role = __user_service.search_user_role(username)os.system("cls")# 循环判断用户角色while True:if role == "新闻编辑":print("新闻编辑的功能列表")elif role == "管理员":print(Fore.LIGHTCYAN_EX, "\n\t1.新闻管理")print(Fore.LIGHTCYAN_EX, "\n\t2.用户管理")print(Fore.LIGHTCYAN_EX, "\n\t3.退出登录")print(Fore.LIGHTCYAN_EX, "\n\t4.退出系统")print(Style.RESET_ALL)opt = input("\n\t输入操作编号")if opt == "1":while True:os.system("cls")print(Fore.LIGHTCYAN_EX, "\n\t1.审批新闻")print(Fore.LIGHTCYAN_EX, "\n\t2.删除新闻")print(Fore.LIGHTCYAN_EX, "\n\t3.返回上一级")print(Style.RESET_ALL)opt = input("\n\t请输入操作编号")if opt == "1":page = 1 # 默认访问第一页while True:os.system("cls")result = __news_service.search_unreview_list(page)# 查询总页数count_page = __news_service.search_unreview_count_page()# 循环获得新闻信息for index in range(len(result)):new = result[index]print(Fore.LIGHTBLUE_EX,"\n\t%d\t%s\t%s\t%s\t"%(index+1,new[1],new[2],new[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.LIGHTBLUE_EX, "\n\tprev.上一页")print(Fore.LIGHTBLUE_EX, "\n\tnext.下一页")print(Fore.LIGHTBLUE_EX, "\n\tback.返回上一层")print(Style.RESET_ALL)opt = input("\n\t请输入操作编号") # 等待控制台输入if opt == "prev" and page>1:page += -1elif opt == "next" and page<count_page:page += 1elif opt == "back":breakelif opt == "2":print("删除新闻")elif opt == "3":breakelif opt == "2":print("用户管理")elif opt == "3":breakelif opt == "4":sys.exit(0)else:print("\n\t登录失败(3秒后自动返回)")time.sleep(3)sys.exit(0)if opt == "2":# 退出系统sys.exit(0)
7.总结
通过控制台界面提供了一个简单的新闻管理系统,
实现了用户登录、角色特定功能展示、新闻审批和系统退出等基本功能。
并通过服务类和控制台交互实现了业务逻辑和用户界面的分离。
功能概述
用户登录:系统提供了一个登录功能,允许用户输入用户名和密码进行身份验证。
用户角色管理:根据用户的角色(如新闻编辑或管理员),系统提供不同的功能菜单。
新闻审批:新闻编辑和管理员可以审批待审批的新闻。
新闻管理:管理员可以执行新闻管理任务,如删除新闻。
系统退出:用户可以随时退出登录或完全退出系统。
功能实现
服务层引入:通过 UserService
和 NewsService
类,系统封装了用户和新闻相关的业务逻辑。
登录验证:用户输入用户名和密码后,UserService
的 login
方法会验证用户身份,并返回验证结果。
安全输入:通过 getpass
库,系统安全地获取用户的密码输入,防止密码在屏幕上显示。
角色查询:登录成功后,UserService
的 search_user_role
方法会查询用户的角色,并根据角色展示相应的功能。
新闻审批:在新闻审批功能中,NewsService
的 search_unreview_list
方法会从数据库中查询待审批的新闻列表,并展示给用户。
分页控制:在新闻审批功能中,用户可以通过输入“prev”和“next”来控制新闻列表的分页浏览。
系统退出:用户选择退出登录或系统时,程序会调用 sys.exit(0)
来结束当前进程。