Last active
July 18, 2016 11:06
-
-
Save takwas/d898eb0e5a5abd28e0f9d7fa43f6b27d to your computer and use it in GitHub Desktop.
Demo: Setup a Flask application
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """ | |
| File: my_flask_app/my_flask_app/__init__.py | |
| my_flask_app | |
| ~~~~~~~~~~~~ | |
| Flask application __init__ demo | |
| :author: Tosin Damilare James Animashaun ([email protected]) | |
| :copyright: (c) 2016 | |
| :license: MIT | |
| """ | |
| # third-party library imports | |
| from flask import Flask | |
| from flask_bootstrap import Bootstrap | |
| from flask_sqlalchemy import SQLAlchemy | |
| from flask_login import LoginManager | |
| from flask_mail import Mail, Message | |
| from flask_socketio import SocketIO, emit | |
| from celery import Celery | |
| # Instantiate Flask extensions | |
| bootstrap = Bootstrap() | |
| db = SQLAlchemy() | |
| login_manager = LoginManager() | |
| mail = Mail() | |
| socketio = SocketIO() | |
| # Setup Celery task queue | |
| job_manager = Celery('my_flask_app') | |
| # Operations on the `LoginManager` Flask extension instance | |
| login_manager.session_protection = 'strong' | |
| login_manager.login_view = 'auth.login' # I have a blueprint called 'auth' | |
| def create_app(config_key): | |
| """ | |
| A factory function to create a Flask application instance and do | |
| some initializations. | |
| """ | |
| # standard library imports | |
| from inspect import getmembers, isfunction | |
| # local imports | |
| from helpers import utils | |
| # module containing custom Jinja2 filters | |
| from . import template_filters | |
| from config import config_dict | |
| configuration = config_dict.get(config_key) | |
| try: | |
| app = Flask(configuration.APP_NAME) | |
| except AttributeError: | |
| app = Flask(__name__) | |
| # Get the configuration settings for this application instance | |
| app.config.from_object(configuration) | |
| # Let's know the mode the app is running in. Create object of config | |
| # instance to get its string representation | |
| print 'Initializing app ...\nMode:\t%r' % configuration() ####DEBUG | |
| # Initialize flask-extensions. Call <init_app> method on each | |
| # extension's instance | |
| configuration.init_app(app, bootstrap, db, login_manager, mail, socketio) | |
| # Update config for Celery instance | |
| job_manager.conf.update(app.config) | |
| # Pass some needed objects into Jinja2 environment globals | |
| jinja_env = app.jinja_env | |
| jinja_env.globals['isinstance'] = isinstance | |
| jinja_env.globals['utils'] = utils | |
| # Import blueprints from blueprint wrapper-modules | |
| from blueprints.mod_auth import auth as a | |
| from blueprints.mod_main import main as b | |
| from blueprints.mod_jobs import jobs as c | |
| from blueprints.mod_settings import settings as d | |
| from blueprints.mod_user import user as e | |
| blueprints = [a, b, c, d, e] | |
| for blueprint in blueprints: | |
| # register template filters (functions) with blueprint | |
| for name, function in getmembers(template_filters): | |
| if isfunction(function): | |
| blueprint.add_app_template_filter(function) | |
| # register blueprints with application | |
| app.register_blueprint(blueprint) | |
| # Build database models | |
| with app.app_context(): | |
| db.create_all() | |
| return app |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """ | |
| File: my_flask_app/config.py | |
| config | |
| ~~~~~~ | |
| Application configuration module. | |
| :author: Tosin Damilare James Animashaun ([email protected]) | |
| :copyright: (c) 2016 | |
| :license: MIT | |
| """ | |
| # standard library imports | |
| import os | |
| # third-party library imports | |
| import shortuuid | |
| # local imports | |
| from my_flask_app.helpers import utils | |
| """ | |
| Global variables | |
| """ | |
| # This will get the absolute path to the module that | |
| # imports this config file using the '__file__' | |
| # attribute. | |
| BASE_URI = os.path.dirname(__file__) | |
| # Get absolute path to user's home directory | |
| HOME_DIR = os.path.expanduser('~/') # '/' is added to ensure the path has a trailing slash | |
| # Let's store the name of the application | |
| # package here. This is recommended to be | |
| # the value of the `import_name` argument | |
| # when creating the `Flask` application object. | |
| APP_NAME = 'my_flask_app' | |
| # Change alphabet being used by module `shortuuid` | |
| # to generate new UUIDs | |
| shortuuid.set_alphabet('jeyc3EfKYiH2jKSo9oJDRefNaCHzZzrjUxRDGRij2z6Uh') | |
| """ | |
| Configuration classes. | |
| `Config` class is the base/super class. | |
| `DevConfig`, `TestingConfig` and `ProductionConfig` all extend the base | |
| class: `Config` | |
| """ | |
| class Config(): | |
| """ | |
| Base configuration class. Has all the common configuration | |
| properties. | |
| """ | |
| # DEBUG config | |
| NUM_DUMMY_USERS = 100 | |
| DEBUG = False | |
| TESTING = False | |
| WTF_CSRF_ENABLED = True | |
| SECRET_KEY = os.environ.get('CSRF_SESSION_SECRET_KEY', | |
| '\x98(\xa8\xf4\xfb1A\x1d4\xfd\\\xb18S\x16\x8c\x9a\xdd\x17o\x1e\x9fZm\xf2\xefZ_\x95\xb0\x9b`\xae\xc4\x98*G\x9e\xdd\xa1\x18\x9cq\xf7\xbd\x18Vr\x1d\xb2!\x14\x84\xd9\xa6\xbfR\xa6\xfa5\xcaN\x11`y\xb9/\xc3x\xb7') # generated with os.urandom(70`)` | |
| SECURITY_PASSWORD_SALT = os.environ.get('SECURITY_PASSWORD_SALT', | |
| shortuuid.random(length=80)) | |
| SQLALCHEMY_COMMIT_ON_TEARDOWN = True | |
| SQLALCHEMY_TRACK_MODIFICATIONS = False # Necessary when using SQLAlchemy event notification system; http://stackoverflow.com/a/33790196/1650240 | |
| THREADS_PER_PAGE = 2 | |
| APP_NAME = APP_NAME | |
| PAGINATION_PER_PAGE = 4 | |
| DEFAULT_IMAGES = { | |
| 'SILHOUETTE_MALE': 'SILHOUETTE_MALE.png', | |
| 'SILHOUETTE_FEMALE': 'SILHOUETTE_FEMALE.png', | |
| 'SILHOUETTE_OTHER': 'SILHOUETTE_OTHER.png' | |
| } | |
| ALLOWED_FILE_EXTENSIONS_PROFILE_IMG = ['.jpg', '.JPG', '.jpeg', '.JPEG', '.png', '.PNG'] | |
| @staticmethod | |
| def init_app(app, *args): | |
| """ | |
| Method to initialize instances of Flask extensions passed in as | |
| a list of parameters. | |
| """ | |
| for flask_extension in args: | |
| flask_extension.init_app(app) | |
| class DevelopmentConfig(Config): | |
| """ | |
| Extends `Config` class. | |
| Contains configuration keys applicable for when developing the app. | |
| """ | |
| # DEBUG config | |
| NUM_DUMMY_USERS = 100 | |
| DEBUG = True | |
| APP_STATIC_DATA_URI = os.path.join(BASE_URI, APP_NAME, 'data') | |
| DUMMY_DATA_DIR = os.path.join(BASE_URI, 'dummy_data/') | |
| # database config | |
| DB_URI = os.path.join(BASE_URI, '.my_flask_app_app_data_dev.sqlite') | |
| SQLALCHEMY_DATABASE_URI = 'sqlite:///' + DB_URI | |
| MEDIA_URI = os.path.join(APP_STATIC_DATA_URI, 'media') | |
| MEDIA_PATHS = { | |
| 'USER_PROFILES': os.path.join(MEDIA_URI, 'images/user_profiles'), | |
| 'DEFAULT_USER_PROFILE_IMAGES': os.path.join(MEDIA_URI, 'images/defaults/user_profiles') | |
| } | |
| # email specifics | |
| MAIL_SENDER = '[email protected]' | |
| MAIL_SERVER = 'smtp.mail.yahoo.com' | |
| MAIL_PORT = 587 | |
| MAIL_USE_TLS = True | |
| MAIL_USE_SSL = False | |
| # email authentication | |
| MAIL_USERNAME = os.environ.get('MY_FLASK_APP_MAIL_USERNAME', MAIL_SENDER) | |
| MAIL_PASSWORD = os.environ.get('MY_FLASK_APP_MAIL_PASSWORD', 'fake') | |
| # Celery configuration | |
| BROKER_URL='redis://localhost:6379/0' | |
| CELERY_RESULT_BACKEND='redis://localhost:6379/0' | |
| def __repr__(self): | |
| """ | |
| Provide a string representation for this configuration mode. | |
| """ | |
| return '<Mode: Development>' | |
| class TestingConfig(Config): | |
| """ | |
| Extends `Config` class. | |
| Contains configuration keys applicable for when running tests of the | |
| app. | |
| """ | |
| TESTING = True | |
| DB_URI = os.path.join(BASE_URI, '.my_flask_app_app_data_test.sqlite') | |
| SQLALCHEMY_DATABASE_URI = 'sqlite:///' + DB_URI | |
| APP_STATIC_DATA_URI = os.path.join(HOME_DIR, '.my_flask_app_app_data_test/static/') | |
| def __repr__(self): | |
| """ | |
| Provide a string representation for this configuration mode. | |
| """ | |
| return '<Mode: Testing>' | |
| class ProductionConfig(Config): | |
| """ | |
| Extends `Config` class. | |
| Contains configuration keys applicable for when deploying the app. | |
| """ | |
| # DEBUG config | |
| NUM_DUMMY_USERS = 1000 | |
| OPENSHIFT_REPO_DIR = os.environ.get('OPENSHIFT_REPO_DIR', '.') | |
| OPENSHIFT_DATA_DIR = os.environ.get('OPENSHIFT_DATA_DIR', BASE_URI) # for hosting on Openshift | |
| APP_STATIC_DATA_URI = OPENSHIFT_DATA_DIR or os.path.join(HOME_DIR, '.my_flask_app_app_production/static/') | |
| DUMMY_DATA_DIR = os.path.join(OPENSHIFT_REPO_DIR, 'dummy_data/') | |
| SECRET_KEY = os.environ.get('OPENSHIFT_SECRET_TOKEN', | |
| '\x98(\xa8\xf4\xfb1A\x1d4\xfd\\\xb18S\x16\x8c\x9a\xdd\x17o\x1e\x9fZm\xf2\xefZ_\x95\xb0\x9b`\xae\xc4\x98*G\x9e\xdd\xa1\x18\x9cq\xf7\xbd\x18Vr\x1d\xb2!\x14\x84\xd9\xa6\xbfR\xa6\xfa5\xcaN\x11`y\xb9/\xc3x\xb7') # generated with `os.urandom(70)` | |
| #DB_USER = os.environ.get('MY_FLASK_APP_DB_USER') or 'admin' | |
| #DB_PWD = os.environ.get('MY_FLASK_APP_DB_PWD') or 'admin' | |
| #SQLALCHEMY_DATABASE_URI = 'postgresql://'+DB_USER+':'+DB_PWD+'@localhost:5432/my_flask_app' | |
| DB_URI = os.path.join(OPENSHIFT_DATA_DIR, '.my_flask_app_app_data.sqlite') | |
| SQLALCHEMY_DATABASE_URI = 'sqlite:///' + DB_URI | |
| MEDIA_URI = os.path.join(APP_STATIC_DATA_URI, 'media') | |
| MEDIA_PATHS = { | |
| 'USER_PROFILES': os.path.join(MEDIA_URI, 'images/user_profiles'), | |
| 'DEFAULT_USER_PROFILE_IMAGES': os.path.join(MEDIA_URI, 'images/defaults/user_profiles') | |
| } | |
| # email specifics | |
| MAIL_SENDER = os.environ.get('MY_FLASK_APP_MAIL_SENDER', '[email protected]') | |
| MAIL_SERVER = 'smtp.mail.yahoo.com' | |
| MAIL_PORT = 587 | |
| MAIL_USE_TLS = True | |
| MAIL_USE_SSL = False | |
| # email authentication | |
| MAIL_USERNAME = os.environ.get('MY_FLASK_APP_MAIL_USERNAME', MAIL_SENDER) | |
| MAIL_PASSWORD = os.environ.get('MY_FLASK_APP_MAIL_PASSWORD', 'fake') | |
| # Celery configuration | |
| BROKER_URL='redis://localhost:6379/0' | |
| CELERY_RESULT_BACKEND='redis://localhost:6379/0' | |
| def __repr__(self): | |
| """ | |
| Provide a string representation for this configuration mode. | |
| """ | |
| return '<Mode: Production>' | |
| config_dict = { 'default_config' : DevelopmentConfig, | |
| 'dev_config' : DevelopmentConfig, | |
| 'test_config' : TestingConfig, | |
| 'production_config' : ProductionConfig | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python | |
| """ | |
| File: my_flask_app/run.py | |
| run | |
| ~~~ | |
| Module to run the whole application | |
| :author: Tosin Damilare James Animashaun ([email protected]) | |
| :copyright: (c) 2016 | |
| :license: MIT | |
| """ | |
| # standard library imports | |
| import os | |
| # third-party library imports | |
| from flask_script import Manager, Shell, Command | |
| # local imports | |
| from my_flask_app import create_app, db | |
| from init_db import DB_Init | |
| # Create new Flask application instance | |
| # Factory function `create_app` takes care of this | |
| app = create_app(os.getenv('MY_FLASK_APP_CONFIG_MODE', default='default_config')) | |
| # Create `Manager` instance for Flask extension "Flask-script" | |
| app_manager = Manager(app) | |
| # Callback function that'll be used for passing objects that we might | |
| # need, to test/run the application within the context of a shell | |
| def make_shell_context(): | |
| return dict(app=app, db=db) | |
| # Add commands to shell context | |
| app_manager.add_command('shell', Shell(make_context=make_shell_context)) | |
| app_manager.add_command('dbnit', DB_Init(app=app)) | |
| # Run the application | |
| if __name__ == '__main__': | |
| app_manager.run() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment