import os from flask import Flask from flask_sqlalchemy import SQLAlchemy from flask_login import LoginManager from flask_migrate import Migrate from config import config from flask_wtf.csrf import CSRFProtect import logging from logging.handlers import RotatingFileHandler # 初始化扩展 db = SQLAlchemy() login_manager = LoginManager() migrate = Migrate() csrf = CSRFProtect() def create_app(config_name='default'): """应用工厂函数""" # 设置模板和静态文件夹 app_dir = os.path.dirname(os.path.abspath(__file__)) template_folder = os.path.join(app_dir, 'web', 'templates') static_folder = os.path.join(os.path.dirname(app_dir), 'static') app = Flask(__name__, template_folder=template_folder, static_folder=static_folder) # 尝试加载.env文件 try: from dotenv import load_dotenv if load_dotenv(): print("成功加载.env文件") else: print("未找到或无法加载.env文件") except ImportError: print("python-dotenv未安装,跳过.env文件加载") app.config.from_object(config[config_name]) config[config_name].init_app(app) # 特别确保MAX_CONTENT_LENGTH配置正确应用 max_content_length = app.config.get('MAX_CONTENT_LENGTH', 16 * 1024 * 1024) app.config['MAX_CONTENT_LENGTH'] = max_content_length print(f"Setting MAX_CONTENT_LENGTH to: {max_content_length} bytes ({max_content_length / (1024*1024)} MB)") # 初始化扩展 db.init_app(app) login_manager.init_app(app) migrate.init_app(app, db) csrf.init_app(app) # 配置登录管理器 login_manager.login_view = 'web.login' login_manager.login_message = '请先登录' login_manager.login_message_category = 'info' login_manager.id_attribute = 'get_id' # 使用 get_id 方法获取用户ID # 注册蓝图 from app.api import api_bp app.register_blueprint(api_bp, url_prefix=f'/api/{app.config["API_VERSION"]}') csrf.exempt(api_bp) from app.web import web_bp app.register_blueprint(web_bp) # 注册错误处理器 from app.web.views import register_error_handlers register_error_handlers(app) # 配置日志 if not app.debug and not app.testing: # 确保日志目录存在 if not os.path.exists('logs'): os.mkdir('logs') # 配置文件日志处理器 file_handler = RotatingFileHandler('logs/kamaxitong.log', maxBytes=10240, 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('KaMiXiTong startup') return app