Skip to content

Instantly share code, notes, and snippets.

@takwas
Last active July 18, 2016 11:06
Show Gist options
  • Select an option

  • Save takwas/d898eb0e5a5abd28e0f9d7fa43f6b27d to your computer and use it in GitHub Desktop.

Select an option

Save takwas/d898eb0e5a5abd28e0f9d7fa43f6b27d to your computer and use it in GitHub Desktop.
Demo: Setup a Flask application
"""
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
"""
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
}
#!/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