Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flask: How to manage different environment databases?

I am working on an app which looks similar to

facebook/
         __init__.py
         feed/
             __init__.py
             business.py
             views.py
             models/
                    persistence.py
                    user.py
         chat/
             __init__.py
             models.py
             business.py
             views.py
         config/
                dev.py
                test.py
                prod.py 

I want to have three environments Dev, Test and Production.
I have the following requirements:
a.) When I start the server python runserver.py, I would like to mention which environment I want to connect - Dev, Test or Production.
b.) Dev & Production should have the schema built and just need to connect to machine
c.) I would also like for my test to connect to sqlite db, and create the schema, run tests

How can I achieve this in a configuration manner so that I do not have to hardcode anything related to database.

Are there any good patterns available in flask?

Currently my runerver.py has hardcoding for environment that I don't like,

app = Flask(__name__)
app.config['SECRET_KEY'] = dev.SECRET_KEY

I am looking for better ideas than I have

like image 573
daydreamer Avatar asked Mar 24 '13 19:03

daydreamer


People also ask

How do I use multiple databases in Flask?

SQLAlchemy can connect to more than one database at a time. It refers to different engines as “binds”. Flask-SQLAlchemy simplifies how binds work by associating each engine with a short string, a “bind key”, and then associating each model and table with a bind key.

What is the best database to use with Flask?

Flask can use SQLite and MySQL as a backend database. We recommend that you use SQLAlchemy as ORM with these relational databases.

How do I change my environment from production in Flask?

It is controlled with the FLASK_ENV environment variable and defaults to production . Setting FLASK_ENV to development will enable debug mode. flask run will use the interactive debugger and reloader by default in debug mode. To control this separately from the environment, use the FLASK_DEBUG flag.

How do I set environment variables in Flask?

Command-line: Similarly, the FLASK_ENV variable sets the environment on which we want our flask application to run. For example, if we put FLASK_ENV=development the environment will be switched to development. By default, the environment is set to development.


3 Answers

Solution I use:

#__init__.py
app = Flask(__name__)
app.config.from_object('settings')
app.config.from_envvar('MYCOOLAPP_CONFIG',silent=True)

On the same level from which application loads:

#settings.py
SERVER_NAME="dev.app.com"
DEBUG=True
SECRET_KEY='xxxxxxxxxx'


#settings_production.py
SERVER_NAME="app.com"
DEBUG=False

So. If Environment Variable MYCOOLAPP_CONFIG does not exist -> only settings.py will load, which refers to default settings (development server as for me)
This is the reason for "silent=True", second config file not required, while settings.py default for development and with default values for common config keys

If any other settings_file will be loaded in addition to first one values inside it overrides values in original one. (in my example DEBUG and SERVER_NAME will be overrided, while SECRET_KEY stays same for all servers)

The only thing you should discover for yourself depends on the way how you launch your application
Before launching ENVVAR MYCOOLAPP_CONFIG should be set
For example I run with supervisor daemon and on production server I just put this in supervisor config file:

environment=MYCOOLAPP_CONFIG="/home/tigra/mycoolapp/settings_production.py"

With this way you can easily manage all your configuration files, moreover, with this way you can exclude this files from git or any other version control utility

default Linux way is this one in console before launching:
export MYCOOLAPP_CONFIG="/home/tigra/mycoolapp/settings_production.py"

like image 133
Tigra Avatar answered Nov 01 '22 07:11

Tigra


I think this is what your looking for:

http://flask.pocoo.org/docs/config/#configuring-from-files

But also checkout the flask-empty project, it's a boilerplate for flask applications with environment specific configurations.

https://github.com/italomaia/flask-empty

You specify your configurations in config.py like so:

class Dev(Config):
    DEBUG = True
    MAIL_DEBUG = True
    SQLALCHEMY_ECHO = True
    SQLALCHEMY_DATABASE_URI = "sqlite:////tmp/%s_dev.sqlite" % project_name

This inherits the Config class which can contain your defaults. From there, main.py has methods for creating a flask instance from the config.py file, manage.py determines which config is loaded.

Here's a snippet from main.py so you get the idea:

def app_factory(config, app_name=None, blueprints=None):
    app_name = app_name or __name__
    app = Flask(app_name)

    config = config_str_to_obj(config)
    configure_app(app, config)
    configure_blueprints(app, blueprints or config.BLUEPRINTS)
    configure_error_handlers(app)
    configure_database(app)
    configure_views(app)

    return app

And then manage.py handles setup of the environment based upon command line arguments passed, however you can get an idea of how it works (note this requires flask-script):

from flask.ext import script

import commands

if __name__ == "__main__":
    from main import app_factory
    import config

    manager = script.Manager(app_factory)
    manager.add_option("-c", "--config", dest="config", required=False, default=config.Dev)
    manager.add_command("test", commands.Test())
    manager.run() 

From here you could choose the required Config class from an environmental variable, or other method of your choosing.

like image 41
Eddie Avatar answered Nov 01 '22 07:11

Eddie


You can create a "config" module which contains the configuration for each environment. Thereafter the currently running environment can be specified by setting a shell variable.

If you are initializing your flask application in the main init file, the configuration also could be set there. This is how I set my configuration:

def setup_config(app):
    """Set the appropriate config based on the environment settings"""
    settings_map = {'development': DevelopmentSettings,
                    'staging': StagingSettings,
                    'testing': TestingSettings,
                    'production': ProductionSettings}
    env = environ['ENV'].lower()
    settings = settings_map[env]
    app.config.from_object(settings)

Setting up environment variable before running the development server or even the tests can be a hassle, therefore I automate these actions with a makefile.

Also take a look at flask-script http://flask-script.readthedocs.org/en/latest/.

like image 31
Ifthikhan Avatar answered Nov 01 '22 08:11

Ifthikhan