Flask Builder¶
Il modulo prompt_versioner.app.flask_builder fornisce la factory per creare l'applicazione web Flask.
create_app¶
Funzione factory per creare e configurare l'applicazione Flask del dashboard web.
Sintassi¶
Parametri:
- versioner (Any): Istanza di PromptVersioner
- config_name (str | None): Nome della configurazione ('development', 'production', o 'default')
Returns:
- Flask: Applicazione Flask configurata
Configurazioni Disponibili¶
L'applicazione supporta diverse configurazioni:
- development: Modalità di sviluppo con debug abilitato
- production: Modalità di produzione ottimizzata
- default: Configurazione di default
La configurazione viene selezionata automaticamente dalla variabile d'ambiente FLASK_ENV se non specificata.
Servizi Inizializzati¶
L'applicazione inizializza automaticamente i seguenti servizi:
- MetricsService: Gestione e analisi delle metriche
- DiffService: Confronto tra versioni
- AlertService: Sistema di notifiche e avvisi
Blueprint Registrati¶
L'applicazione registra i seguenti blueprint:
- prompts_bp: Gestione dei prompt
- versions_bp: Gestione delle versioni
- alerts_bp: Gestione degli avvisi
- export_import_bp: Import/export dei dati
Route Principali¶
/ (GET)¶
Route principale che renderizza la dashboard.
Returns:
- Template dashboard.html con interfaccia principale
Gestione Errori¶
L'applicazione include gestori per errori comuni:
404 - Not Found¶
Returns:
- {"error": "Not found"} con status code 404
500 - Internal Server Error¶
Returns:
- {"error": "Internal server error"} con status code 500
Esempio di Utilizzo¶
Utilizzo Base¶
from prompt_versioner.app.flask_builder import create_app
from prompt_versioner import PromptVersioner
# Inizializza versioner
versioner = PromptVersioner("my_prompts.db")
# Crea app Flask
app = create_app(versioner, config_name="development")
# Avvia server di sviluppo
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000, debug=True)
Utilizzo con Configurazione Personalizzata¶
import os
from prompt_versioner.app.flask_builder import create_app
from prompt_versioner import PromptVersioner
# Configura ambiente
os.environ["FLASK_ENV"] = "production"
# Inizializza con database esistente
versioner = PromptVersioner("production_prompts.db")
# Crea app per produzione
app = create_app(versioner)
# L'app è pronta per deployment con WSGI server
Accesso ai Servizi¶
# All'interno dell'applicazione Flask, i servizi sono accessibili tramite app
@app.route("/api/custom-metrics")
def custom_metrics():
    # Accesso al MetricsService
    metrics_service = app.metrics_service
    stats = metrics_service.get_overall_stats()
    return {"stats": stats}
@app.route("/api/compare/<version_a>/<version_b>")
def compare_versions(version_a: str, version_b: str):
    # Accesso al DiffService
    diff_service = app.diff_service
    diff = diff_service.compare_versions(version_a, version_b)
    return {"diff": diff}
Deployment con Gunicorn¶
# app.py
from prompt_versioner.app.flask_builder import create_app
from prompt_versioner import PromptVersioner
# Crea app per produzione
versioner = PromptVersioner("prompts.db")
app = create_app(versioner, "production")
if __name__ == "__main__":
    app.run()
Deployment con Docker¶
# Dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
# Esponi porta
EXPOSE 5000
# Avvia applicazione
CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:5000", "app:app"]
# docker-compose.yml
version: '3.8'
services:
  prompt-versioner:
    build: .
    ports:
      - "5000:5000"
    volumes:
      - ./data:/app/data
    environment:
      - FLASK_ENV=production
Personalizzazione¶
Aggiunta di Route Personalizzate¶
from prompt_versioner.app.flask_builder import create_app
# Crea app base
app = create_app(versioner)
# Aggiungi route personalizzate
@app.route("/api/health")
def health_check():
    return {"status": "healthy", "version": "1.0.0"}
@app.route("/api/custom-dashboard")
def custom_dashboard():
    # Logica personalizzata per dashboard
    versioner = app.versioner
    prompts = versioner.list_prompts()
    return {"prompts": prompts}
Middleware Personalizzato¶
from flask import request, jsonify
import time
# Aggiungi middleware per logging delle richieste
@app.before_request
def log_request():
    request.start_time = time.time()
@app.after_request
def log_response(response):
    duration = time.time() - request.start_time
    print(f"{request.method} {request.path} - {response.status_code} ({duration:.3f}s)")
    return response
Configurazione Personalizzata¶
# custom_config.py
import os
class CustomConfig:
    SECRET_KEY = os.environ.get('SECRET_KEY') or 'dev-secret-key'
    TEMPLATE_FOLDER = 'custom_templates'
    STATIC_FOLDER = 'custom_static'
    # Configurazioni personalizzate
    CUSTOM_FEATURE_ENABLED = True
    API_RATE_LIMIT = 100
# Usa configurazione personalizzata
app = create_app(versioner)
app.config.from_object(CustomConfig)
Integrazione con Autenticazione¶
from flask_login import LoginManager, login_required
# Aggiungi autenticazione
def create_authenticated_app(versioner):
    app = create_app(versioner)
    # Configura LoginManager
    login_manager = LoginManager()
    login_manager.init_app(app)
    login_manager.login_view = 'auth.login'
    # Proteggi route sensibili
    @app.before_request
    def require_auth():
        if request.endpoint and not request.endpoint.startswith('auth.'):
            # Richiedi autenticazione per tutte le route eccetto auth
            pass
    return app
Monitoraggio e Logging¶
import logging
from flask.logging import default_handler
def configure_logging(app):
    # Rimuovi handler default in produzione
    if app.config.get('ENV') == 'production':
        app.logger.removeHandler(default_handler)
    # Configura logging personalizzato
    handler = logging.StreamHandler()
    handler.setFormatter(logging.Formatter(
        '[%(asctime)s] %(levelname)s in %(module)s: %(message)s'
    ))
    app.logger.addHandler(handler)
    app.logger.setLevel(logging.INFO)
# Usa con l'app
app = create_app(versioner)
configure_logging(app)
Struttura dell'Applicazione¶
L'applicazione Flask creata dalla factory ha la seguente struttura:
Flask App
├── Templates (dashboard.html, etc.)
├── Static Files (CSS, JS, images)
├── Services
│   ├── MetricsService (analisi metriche)
│   ├── DiffService (confronti versioni)
│   └── AlertService (notifiche)
├── Controllers (Blueprint)
│   ├── prompts_bp (gestione prompt)
│   ├── versions_bp (gestione versioni)
│   ├── alerts_bp (gestione avvisi)
│   └── export_import_bp (import/export)
└── Error Handlers (404, 500)
Sicurezza¶
Configurazione Sicura¶
class ProductionConfig:
    SECRET_KEY = os.environ.get('SECRET_KEY')  # Sempre da variabile d'ambiente
    SESSION_COOKIE_SECURE = True  # Solo HTTPS
    SESSION_COOKIE_HTTPONLY = True  # Proteggi da XSS
    SESSION_COOKIE_SAMESITE = 'Lax'  # Protezione CSRF
    # Configurazioni sicurezza aggiuntive
    WTF_CSRF_ENABLED = True
    WTF_CSRF_TIME_LIMIT = 3600
Rate Limiting¶
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
def add_rate_limiting(app):
    limiter = Limiter(
        app,
        key_func=get_remote_address,
        default_limits=["200 per day", "50 per hour"]
    )
    # Rate limit specifici per API
    @app.route("/api/metrics")
    @limiter.limit("10 per minute")
    def api_metrics():
        return app.metrics_service.get_summary()