import os from flask import Flask from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate from flask_login import LoginManager from flask_bcrypt import Bcrypt from app.config import config # Initialize extensions db = SQLAlchemy() migrate = Migrate() login_manager = LoginManager() bcrypt = Bcrypt() def create_app(config_name='default'): """Application factory pattern.""" app = Flask(__name__) # Load configuration app.config.from_object(config[config_name]) # Initialize extensions db.init_app(app) migrate.init_app(app, db) bcrypt.init_app(app) # Configure Flask-Login login_manager.init_app(app) login_manager.login_view = 'auth.login' login_manager.login_message = 'Please log in to access this page.' login_manager.login_message_category = 'info' # User loader for Flask-Login from app.models.user import User @login_manager.user_loader def load_user(user_id): return User.query.get(int(user_id)) # Register blueprints from app.routes.auth import auth_bp from app.routes.main import main_bp from app.routes.sets import sets_bp from app.routes.instructions import instructions_bp from app.routes.admin import admin_bp from app.routes.extra_files import extra_files_bp app.register_blueprint(auth_bp) app.register_blueprint(main_bp) app.register_blueprint(sets_bp) app.register_blueprint(instructions_bp) app.register_blueprint(admin_bp) app.register_blueprint(extra_files_bp) # Import models to ensure they're registered with SQLAlchemy from app.models.user import User from app.models.set import Set from app.models.instruction import Instruction from app.models.extra_file import ExtraFile # Create upload directories os.makedirs(os.path.join(app.config['UPLOAD_FOLDER'], 'pdfs'), exist_ok=True) os.makedirs(os.path.join(app.config['UPLOAD_FOLDER'], 'images'), exist_ok=True) os.makedirs(os.path.join(app.config['UPLOAD_FOLDER'], 'covers'), exist_ok=True) os.makedirs(os.path.join(app.config['UPLOAD_FOLDER'], 'thumbnails'), exist_ok=True) os.makedirs(os.path.join(app.config['UPLOAD_FOLDER'], 'extra_files'), exist_ok=True) # Context processor for global template variables @app.context_processor def inject_global_vars(): from app.services.brickset_api import BricksetAPI return { 'app_name': 'LEGO Instructions Manager', 'brickset_available': BricksetAPI.is_configured() } return app