Newer
Older
import sys
import os
from flask_migrate import Migrate
from flask import Flask, send_from_directory, request, redirect
from flask_cors import CORS
from flask_compress import Compress
from database.db import lookup_db_for_binding, init_all_dbs_with_app, init_binding_to_db_for_bindings
from config.config import DEBUG_MODE, get_app_config, get_static_url
# The environment variable whose value is the PORT this application will listen on
PORT_ENV_VAR_KEY = "PORT"
# Create and configure our Flask app
app = Flask(__name__, static_url_path=get_static_url())
app.url_map.strict_slashes = False
# Enable Gzip Compression on all responses
Compress(app)
# Enable CORS for all routes
CORS(app)
# NOTE: if there is an error in your route, e.g.: printing a variable that doesn't
# exist, then you will get a CORS related error which has nothing to do with CORS
# Source: https://stackoverflow.com/questions/25594893/how-to-enable-cors-in-flask
# Load config
flask_app_config = get_app_config()
app.config.from_object(flask_app_config)
init_binding_to_db_for_bindings(flask_app_config.SQLALCHEMY_BINDS.keys())
# Initialise all databases
init_all_dbs_with_app(app)
# The import below registers all models to their respective database
from models import *
# Register all blueprints/routes
from blueprints import home_blueprint, persons_blueprint
# from blueprints.auth import auth_blueprint
app.register_blueprint(home_blueprint)
app.register_blueprint(persons_blueprint)
# app.register_blueprint(auth_blueprint)
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# ===================== MIGRATION SETUP =====================
APP_CONFIG_BINDINGS_DICT_KEY = "SQLALCHEMY_BINDS"
# The below environment variables should be set by the script that initializes the migration
# This environment variable is used by "Flask_Migrate" and should not be changed
FLASK_MIGRATE_FLASK_APP_ENV_VAR_KEY = "FLASK_APP"
# This environment variable is a hack to specify the DB we want to migrate, since we have multiple dbs
# and only require/want to migrate one at a time.
FLASK_DB_BINDING_ENV_VAR_KEY = "FLASK_DB_BINDING_TO_MIGRATE"
MIGRATION_MODE = os.environ.get(FLASK_MIGRATE_FLASK_APP_ENV_VAR_KEY, None) is not None
if MIGRATION_MODE:
binding_name = os.environ.get(FLASK_DB_BINDING_ENV_VAR_KEY, None)
if not binding_name:
print("Invalid binding name specified:", binding_name)
exit(-1)
with app.app_context():
print("Initializing migration")
# Source: https://flask-migrate.readthedocs.io/en/latest/
# After the extension is initialized, a "db" group will be added to the command-line options with several
# sub-commands
bindings_dict = app.config[APP_CONFIG_BINDINGS_DICT_KEY]
# Set the main db
app.config["SQLALCHEMY_DATABASE_URI"] = bindings_dict[binding_name]
# engine = db.get_engine(flask_app, bind_name)
migrate = Migrate()
# "db" arg below needs to be the database you want the above main db to become/migrate to
db_to_migrate = lookup_db_for_binding(binding_name)
migrate.init_app(app, db_to_migrate)
# ===================== End MIGRATION SETUP. =====================
# Get arguments to this program call
if not MIGRATION_MODE:
# The Flask Migrate CLI passes arguments from its own CLI, and we don't want to handle those.
from cli_handler import handle_cli
cli_args = sys.argv[1:]
if len(cli_args) > 0:
if DEBUG_MODE:
with app.app_context():
handle_cli(app, lookup_db_for_binding, cli_args)
exit(1)
else:
print("!!!WARNING!!! Application should not be run with CLI arguments, "
"if you intended to run the CLI please run in development mode.")
exit(-1)
# Serve all static assets for the frontend
@app.route('/static/<path:path>')
def serve_static_files(path):
return send_from_directory('static', path)
# Force secure connection
@app.before_request
def before_request():
if not DEBUG_MODE:
scheme = request.headers.get('X-Forwarded-Proto')
if scheme and scheme == 'http' and request.url.startswith('http://'):
url = request.url.replace('http://', 'https://', 1)
code = 301
return redirect(url, code=code)
# Hook any custom Jinja templating functions
from config import CUSTOM_TEMPLATE_FUNCTIONS
app.jinja_env.globals.update(CUSTOM_TEMPLATE_FUNCTIONS)
if __name__ == '__main__':
host = '127.0.0.1'
port = int(os.environ.get(PORT_ENV_VAR_KEY, 5000))
if DEBUG_MODE:
mode_desc = "debug"
else:
mode_desc = "production"
# NOTE: it will say "Environment: production", but if DEBUG_MODE=True, then ignore that.
app.run(debug=DEBUG_MODE, host=host, port=port)
print(f"!!!WARNING!!! Running in {mode_desc} mode")