"""App-Factory für den Projekt-Hub. Erzeugt die Flask-App, lädt die Config, bindet die Extensions und registriert die Blueprints der einzelnen Mini-App-Module. Jedes neue Modul wird hier per register_blueprint(...) eingebunden und über die zentrale Navigations-Registry in der Navigation sichtbar gemacht — Kern bleibt unangetastet. """ import os from flask import Flask, redirect, url_for from .config import get_config from .extensions import db, migrate, login_manager, mail, limiter, csrf # --- Zentrale Navigations-Registry --------------------------------------- # Jedes Modul trägt hier einen Eintrag bei (Label, Endpoint, Icon). base.html # rendert daraus die gemeinsame Navigation. Neues Modul = neuer Eintrag. NAV_MODULES = [ {"label": "Projekte", "endpoint": "projects.index", "icon": "📁"}, ] def create_app(config_name: str | None = None) -> Flask: app = Flask( __name__, instance_relative_config=True, instance_path=os.path.join(os.path.dirname(os.path.dirname(__file__)), "instance"), ) app.config.from_object(get_config(config_name)) # instance/-Ordner sicherstellen (SQLite-Datei landet hier). os.makedirs(app.instance_path, exist_ok=True) # Relativen sqlite-Pfad in den instance/-Ordner umbiegen. uri = app.config.get("SQLALCHEMY_DATABASE_URI", "") if uri.startswith("sqlite:///") and not uri.startswith("sqlite:////"): db_name = uri.replace("sqlite:///", "", 1) abs_path = os.path.join(app.instance_path, db_name) app.config["SQLALCHEMY_DATABASE_URI"] = f"sqlite:///{abs_path}" _init_extensions(app) _register_blueprints(app) _register_context(app) @app.route("/") def index(): return redirect(url_for("projects.index")) return app def _init_extensions(app: Flask) -> None: db.init_app(app) migrate.init_app(app, db) login_manager.init_app(app) mail.init_app(app) limiter.init_app(app) csrf.init_app(app) # Modelle importieren, damit SQLAlchemy/Alembic sie kennen (Autogenerate). from . import models # noqa: F401 from .projects import models as project_models # noqa: F401 from .models import User @login_manager.user_loader def load_user(user_id): return db.session.get(User, int(user_id)) def _register_blueprints(app: Flask) -> None: from .auth import bp as auth_bp from .projects import bp as projects_bp app.register_blueprint(auth_bp) app.register_blueprint(projects_bp) def _register_context(app: Flask) -> None: @app.context_processor def inject_nav(): # Navigations-Registry in allen Templates verfügbar machen. return {"nav_modules": NAV_MODULES}