diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cab2a73 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +*.log +venv/ +*.pyc \ No newline at end of file diff --git a/README.md b/README.md index 5f23e42..dcc46f9 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,11 @@ Web application for sepsis clinical assessment scores using batch ICU patient data Backend of the application will be in Flask and the project will be completely python based Frontend will be purely based on html, css and may be on javascript. + +# Dependencies +1. Python 3.7 + +# Installation +1. Setup virtualenv for the project by running `virtualenv -p python3 venv` +2. Activate the environment by `source venv/bin/activate` +3. Install project requirements using `pip install -r requirements.txt` \ No newline at end of file diff --git a/__init__.py b/__init__.py new file mode 100755 index 0000000..e69de29 diff --git a/requirements.txt b/requirements.txt new file mode 100755 index 0000000..319f9b8 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,10 @@ +Click==7.0 +Flask==1.1.1 +Flask-Cors==3.0.8 +Flask-SQLAlchemy==2.4.0 +itsdangerous==1.1.0 +Jinja2==2.10.1 +MarkupSafe==1.1.1 +six==1.12.0 +SQLAlchemy==1.3.6 +Werkzeug==0.15.5 diff --git a/run.py b/run.py new file mode 100755 index 0000000..7c6c1fb --- /dev/null +++ b/run.py @@ -0,0 +1,4 @@ +from scasBackend import app + +if __name__ == '__main__': + app.run() \ No newline at end of file diff --git a/scasBackend/__init__.py b/scasBackend/__init__.py new file mode 100755 index 0000000..ebcc660 --- /dev/null +++ b/scasBackend/__init__.py @@ -0,0 +1,55 @@ +from flask import abort, Flask, request + +from scasBackend.utils import get_instance_folder_path +from scasBackend.api_routes import * +from scasBackend.config import configure_app +from scasBackend.models import db +from flask_cors import CORS + + +app = Flask( + __name__, + instance_path=get_instance_folder_path(), + instance_relative_config=True) + +configure_app(app) # load configurations +db.init_app(app) # init app to db +CORS(app) #Cross Origin Resource Sharing Plugin + +@app.errorhandler(404) +def page_not_found(error): + app.logger.error('Page not found: %s', (request.path, error)) + return "404" + +@app.errorhandler(500) +def internal_server_error(error): + app.logger.error('Server Error: %s', (error)) + return "500" + +@app.errorhandler(Exception) +def unhandled_exception(error): + app.logger.exception(error) + app.logger.error('Unhandled Exception: %s', (error)) + return "500" + +@app.before_first_request +def initialize_database(): + db.create_all() + +@app.after_request +def after_request(response): + header = response.headers + header['Access-Control-Allow-Origin'] = '*' + return response + +@app.route('/') +@app.route('//') +def home(lang_code=None): + return "homepage" + abort(404) + + +# register all routes +app.register_blueprint(api_routes, url_prefix='/api/v1') + +############################################################################### diff --git a/scasBackend/api_routes/__init__.py b/scasBackend/api_routes/__init__.py new file mode 100755 index 0000000..f47e650 --- /dev/null +++ b/scasBackend/api_routes/__init__.py @@ -0,0 +1,4 @@ +from flask import Blueprint +api_routes = Blueprint('api_routes', __name__) + +from .index import * \ No newline at end of file diff --git a/scasBackend/api_routes/index.py b/scasBackend/api_routes/index.py new file mode 100755 index 0000000..93d0919 --- /dev/null +++ b/scasBackend/api_routes/index.py @@ -0,0 +1,7 @@ +from flask import current_app +from . import api_routes + +@api_routes.route('/') +def index(): + current_app.logger.info('/api/v1/') + return "this is /api/v1/" \ No newline at end of file diff --git a/scasBackend/config.py b/scasBackend/config.py new file mode 100755 index 0000000..ac450fe --- /dev/null +++ b/scasBackend/config.py @@ -0,0 +1,50 @@ +from scasBackend.models import db +import os +import logging + +# Configs + +class BaseConfig(object): + DEBUG = False + TESTING = False + # sqlite :memory: identifier is the default if no filepath is present + SQLALCHEMY_DATABASE_URI = 'sqlite://' + SECRET_KEY = '123' + LOGGING_FORMAT = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' + LOGGING_LOCATION = 'scasBackend.log' + LOGGING_LEVEL = logging.DEBUG + SECURITY_CONFIRMABLE = False + SUPPORTED_LANGUAGES = {'en': 'English'} + +# Development +class DevelopmentConfig(BaseConfig): + DEBUG = True + TESTING = False + SQLALCHEMY_DATABASE_URI = 'sqlite:///scasBackend.sqlite3' + SECRET_KEY = '456' + +# Testing +class TestingConfig(BaseConfig): + DEBUG = False + TESTING = True + SQLALCHEMY_DATABASE_URI = 'sqlite://scasBackend.sqlite3' + SECRET_KEY = '789' + +config = { + "development": "scasBackend.config.DevelopmentConfig", + "testing": "scasBackend.config.TestingConfig", + "default": "scasBackend.config.DevelopmentConfig" +} + +def configure_app(app): + # Configure above configuraton + config_name = os.getenv('FLASK_CONFIGURATION', 'default') + app.config.from_object(config[config_name]) + app.config.from_pyfile('config.cfg', silent=True) # if it exists (for production) + + # Configure logging + handler = logging.FileHandler(app.config['LOGGING_LOCATION']) + handler.setLevel(app.config['LOGGING_LEVEL']) + formatter = logging.Formatter(app.config['LOGGING_FORMAT']) + handler.setFormatter(formatter) + app.logger.addHandler(handler) \ No newline at end of file diff --git a/scasBackend/models/__init__.py b/scasBackend/models/__init__.py new file mode 100755 index 0000000..589c64f --- /dev/null +++ b/scasBackend/models/__init__.py @@ -0,0 +1,2 @@ +from flask_sqlalchemy import SQLAlchemy +db = SQLAlchemy() \ No newline at end of file diff --git a/scasBackend/models/base.py b/scasBackend/models/base.py new file mode 100755 index 0000000..0de8e0c --- /dev/null +++ b/scasBackend/models/base.py @@ -0,0 +1,22 @@ +from . import db + +class Base(db.Model): + __abstract__ = True + + created_on = db.Column(db.DateTime, default=db.func.now()) + updated_on = db.Column(db.DateTime, default=db.func.now(), onupdate=db.func.now()) + + def serialize(self, return_fields=[]): + serialize_exclude = getattr(self, '__serialize_exclude__', set()) + return_fields = self.__dict__.keys() if not return_fields else return_fields + return { + key: value for key, value in self.__dict__.items() + # Do not serialize 'private' attributes + # (SQLAlchemy-internal attributes are among those, too) + if not key.startswith('_') + and key in return_fields + and key not in serialize_exclude} + + def create(self): + db.session.add(self) + db.session.commit() \ No newline at end of file diff --git a/scasBackend/utils.py b/scasBackend/utils.py new file mode 100755 index 0000000..de7a89c --- /dev/null +++ b/scasBackend/utils.py @@ -0,0 +1,7 @@ +import os + +def get_app_base_path(): + return os.path.dirname(os.path.realpath(__file__)) + +def get_instance_folder_path(): + return os.path.join(get_app_base_path(), 'instance')