More convenient project initialization, with database initialization added to app.py.

This commit is contained in:
戒酒的李白
2025-01-09 23:30:15 +08:00
parent a30773715e
commit e58f105761
5 changed files with 186 additions and 91 deletions
+115 -22
View File
@@ -1,10 +1,104 @@
from flask import Flask, session, request, redirect, render_template
import re
from apscheduler.schedulers.background import BackgroundScheduler
import subprocess
import os
from pytz import utc
import re
import logging
import getpass
import pymysql
import subprocess
from flask import Flask, session, request, redirect, render_template
from apscheduler.schedulers.background import BackgroundScheduler
from pytz import utc
# 初始化日志记录
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s [%(levelname)s] %(message)s',
handlers=[
logging.FileHandler("app.log"),
logging.StreamHandler()
]
)
def get_db_connection_interactive():
"""
通过终端交互获取数据库连接参数,若按回车则使用默认值。
返回一个连接对象。
"""
print("请依次输入数据库连接信息(直接按回车使用默认值):")
host = input(" 1. 主机 (默认: localhost): ") or "localhost"
port_str = input(" 2. 端口 (默认: 3306): ") or "3306"
try:
port = int(port_str)
except ValueError:
logging.warning("端口号无效,使用默认端口 3306。")
port = 3306
user = input(" 3. 用户名 (默认: root): ") or "root"
password = getpass.getpass(" 4. 密码 (默认: 12345678): ") or "12345678"
db_name = input(" 5. 数据库名 (默认: Weibo_PublicOpinion_AnalysisSystem): ") or "Weibo_PublicOpinion_AnalysisSystem"
logging.info(f"尝试连接到数据库: {user}@{host}:{port}/{db_name}")
try:
connection = pymysql.connect(
host=host,
port=port,
user=user,
password=password,
database=db_name,
charset='utf8mb4',
cursorclass=pymysql.cursors.DictCursor # 返回字典格式
)
logging.info("数据库连接成功。")
return connection
except pymysql.MySQLError as e:
logging.error(f"数据库连接失败: {e}")
exit(1)
def initialize_database(connection, sql_file_path):
"""
执行 SQL 文件中的语句以初始化数据库。
:param connection: 已建立的数据库连接
:param sql_file_path: SQL 文件的路径
"""
try:
with open(sql_file_path, 'r', encoding='utf8') as file:
sql_commands = file.read()
with connection.cursor() as cursor:
for statement in sql_commands.split(';'):
statement = statement.strip()
if statement:
cursor.execute(statement)
connection.commit()
logging.info("数据库初始化成功。")
except FileNotFoundError:
logging.error(f"SQL 文件未找到: {sql_file_path}")
exit(1)
except pymysql.MySQLError as e:
logging.error(f"执行 SQL 时出错: {e}")
connection.rollback()
exit(1)
except Exception as e:
logging.error(f"初始化数据库时出错: {e}")
connection.rollback()
exit(1)
def prompt_first_run():
"""
询问用户是否首次运行,需要初始化数据库。
:return: BooleanTrue 表示需要初始化数据库
"""
while True:
choice = input("是否首次运行该项目,需要初始化数据库?(Y/n): ").strip().lower()
if choice in ['y', 'yes', '']:
return True
elif choice in ['n', 'no']:
return False
else:
print("请输入 Y 或 N。")
# 初始化 Flask 应用
app = Flask(__name__)
@@ -14,25 +108,13 @@ app.secret_key = 'this is secret_key you know ?' # 设置 Flask 的密钥,用
from views.page import page
from views.user import user
app.register_blueprint(page.pb) # 注册页面蓝图
app.register_blueprint(user.ub) # 注册用户蓝图
app.register_blueprint(user.ub) # 注册用户蓝图
# 首页路由,清空 session
@app.route('/')
def hello_world():
return session.clear() # 清空 session,用户退出登录
"""
@app.before_request
def before_reuqest():
pat = re.compile(r'^/static') # 正则匹配静态文件路径
if re.search(pat, request.path): # 如果是静态文件,直接返回
return
elif request.path == '/user/login' or request.path == '/user/register': # 登录或注册页面无需验证
return
elif session.get('username'): # 如果 session 中有用户名,则允许继续
return
return redirect('/user/login') # 否则重定向到登录页面
"""
session.clear() # 清空 session,用户退出登录
return "Session Cleared"
# 中间件:处理请求前的逻辑
@app.before_request
@@ -79,6 +161,19 @@ def run_script():
# 主程序入口
if __name__ == '__main__':
# 检测是否需要初始化数据库
if prompt_first_run():
# 获取数据库连接
connection = get_db_connection_interactive()
# 执行数据库初始化
sql_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'createTables.sql')
initialize_database(connection, sql_file)
# 关闭数据库连接
connection.close()
logging.info("数据库连接已关闭。")
# 设置定时任务,定期执行爬虫脚本
scheduler = BackgroundScheduler(timezone=utc) # 创建后台任务调度器
scheduler.add_job(run_script, 'interval', hours=5) # 每5小时执行一次爬虫脚本
@@ -90,8 +185,6 @@ if __name__ == '__main__':
scheduler.shutdown() # 确保在应用关闭时关闭调度器
# 设置日志记录,捕获应用的请求信息
logging.basicConfig(level=logging.INFO) # 配置日志记录,设置日志级别为 INFO
@app.before_request
def log_request_info():
# 记录每次请求的信息,便于调试和监控