Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get app config from database entries

I'm looking for a way to set some static app config value (as werkzeug server port) from database entries. My app uses SQLAlchemy and blueprints, and currently gets config from an object (config.py).

Assuming the configuration for the database still comes from a config file, how can I configure the rest of the application from a database?

like image 890
27nov Avatar asked Nov 24 '14 17:11

27nov


1 Answers

Read the key/value items from a table and set the config from those items. Keep in mind that the value column can only have one type (I've gone with String here). One way to solve this is to create polymorphic tables with different value types, but that's beyond the scope of this answer. I've solved it here by explicitly naming keys that should be a different type.

import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

# assuming the database is an sqlite file "app.db" in the instance folder
app.config['SQLALCHEMY_DATABASE_URI'] = os.path.join(app.instance_path, 'app.db')
db = SQLAlchemy()
db.init_app(app)


class ConfigItem(db.Model):
    """Represents one config item.

    All values are strings, so non-string values must be converted later.

    :param key: config key
    :param value: configured value
    """

    __tablename__ = 'config_item'

    key = db.Column(db.String, primary_key=True)
    value = db.Column(db.String)

    def __str__(self):
        return '{}: {}'.format(self.key, self.value)

    def __repr__(self):
        return 'ConfigItem(key={!r}, value={!r})'.format(self.key, self.value)


# map a converter function to key names, so that values will be converted from strings to the correct type
# this is just the mapper for Flask config keys, the list will be much longer will extension config keys added
config_types = {
    lambda value: value == 'True': ('DEBUG', 'PROPAGATE_EXCEPTIONS', 'PRESERVE_CONTEXT_ON_EXCEPTION', 'SESSION_COOKIE_HTTPONLY', 'SESSION_COOKIE_SECURE', 'USE_X_SENDFILE', 'TRAP_HTTP_EXCEPTIONS', 'TRAP_BAD_REQUEST_ERRORS', 'JSON_AS_ASCII', 'JSON_SORT_KEYS', 'JSONIFY_PRETTYPRINT_REGULAR'),
    int: ('PERMANENT_SESSION_LIFETIME', 'MAX_CONTENT_LENGTH', 'SEND_FILE_MAX_AGE_DEFAULT')
}
# convert the type to key list mapping above to a key to type mapping
config_types = {key: type for type, keys in config_types.items() for key in keys}

# flask_sqlalchemy database connections only work in an app context
# we're not in a request handler, so have to create the context explicitly
with app.app_context():
    for item in ConfigItem.query:
        # set the config value for each key, converting it if it's not a string
        if item.key in config_types:
            app.config[item.key] = config_types[item.key](value)
        else:
            app.config[item.key.upper()] = item.value
like image 120
davidism Avatar answered Oct 18 '22 21:10

davidism