from flask import Flask from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate from flask_login import LoginManager from flask_session import Session from flask_wtf.csrf import CSRFProtect from config import config from flask_bootstrap import Bootstrap import logging from logging.handlers import RotatingFileHandler import os from datetime import datetime, timedelta import glob # 初始化扩展 db = SQLAlchemy() migrate = Migrate() login_manager = LoginManager() sess = Session() csrf = CSRFProtect() bootstrap = Bootstrap() login_manager.login_view = 'auth.login' def create_app(config_name='default'): """应用工厂函数,创建并配置Flask应用实例""" app = Flask(__name__) # 加载配置 app.config.from_object(config[config_name]) config[config_name].init_app(app) # 配置代理转发 from werkzeug.middleware.proxy_fix import ProxyFix app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1) # 初始化扩展 db.init_app(app) migrate.init_app(app, db) login_manager.init_app(app) sess.init_app(app) csrf.init_app(app) bootstrap.init_app(app) # 配置日志 if not os.path.exists('logs'): os.mkdir('logs') # 清理过期日志 log_retention_days = int(os.environ.get('LOG_RETENTION_DAYS', 7)) cutoff_time = datetime.now() - timedelta(days=log_retention_days) for log_file in glob.glob('logs/*.log*'): if os.path.getmtime(log_file) < cutoff_time.timestamp(): os.remove(log_file) file_handler = RotatingFileHandler('logs/pt_blacklist.log', maxBytes=10240000, backupCount=10) file_handler.setFormatter(logging.Formatter( '%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]' )) file_handler.setLevel(logging.INFO) app.logger.addHandler(file_handler) app.logger.setLevel(logging.INFO) app.logger.info('PT黑名单系统启动') # 注册自定义过滤器 from .filters import translate_status, translate_reason app.jinja_env.filters['translate_status'] = translate_status app.jinja_env.filters['translate_reason'] = translate_reason # 注册蓝图 from .routes import main as main_blueprint app.register_blueprint(main_blueprint) from .auth import auth as auth_blueprint app.register_blueprint(auth_blueprint, url_prefix='/auth') return app