__init__.py 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. import os
  2. from flask import Flask, send_from_directory
  3. from flask_sqlalchemy import SQLAlchemy
  4. from flask_migrate import Migrate
  5. from flask_cors import CORS
  6. from config.settings import config
  7. db = SQLAlchemy()
  8. migrate = Migrate()
  9. def create_app(config_name=None):
  10. """Application factory pattern"""
  11. if config_name is None:
  12. config_name = os.environ.get('FLASK_ENV', 'development')
  13. # Check if static folder exists (for Docker deployment)
  14. static_folder = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'static')
  15. if os.path.exists(static_folder):
  16. app = Flask(__name__, static_folder=static_folder, static_url_path='')
  17. else:
  18. app = Flask(__name__)
  19. app.config.from_object(config[config_name])
  20. # Initialize extensions
  21. db.init_app(app)
  22. migrate.init_app(app, db)
  23. CORS(app)
  24. # Create upload directories
  25. os.makedirs(app.config.get('UPLOAD_FOLDER', 'uploads'), exist_ok=True)
  26. os.makedirs(app.config.get('REPORTS_FOLDER', 'reports'), exist_ok=True)
  27. # Register blueprints
  28. from app.api import api_bp
  29. app.register_blueprint(api_bp, url_prefix='/api')
  30. # Register error handlers
  31. from app.errors import register_error_handlers
  32. register_error_handlers(app)
  33. # Serve frontend static files (for Docker deployment)
  34. # This must be registered AFTER error handlers to properly catch SPA routes
  35. if app.static_folder and os.path.exists(app.static_folder):
  36. @app.route('/')
  37. def serve_index():
  38. return send_from_directory(app.static_folder, 'index.html')
  39. # Catch-all route for SPA - must be the last route registered
  40. @app.errorhandler(404)
  41. def serve_spa(error):
  42. # Check if this is an API request
  43. from flask import request
  44. if request.path.startswith('/api/'):
  45. # Return JSON error for API requests
  46. return {'error': {'code': 'RESOURCE_NOT_FOUND', 'message': 'Resource not found'}}, 404
  47. # For non-API requests, serve index.html for SPA routing
  48. return send_from_directory(app.static_folder, 'index.html')
  49. return app