0

OK, I am trying to do something a little bit esoteric with my Flask application.

I want to have some conditional logic in the model structure that is based on information in a configuration file.

At present when I call my Flask App, a configuration object is specified like this:

app = create_app('swarm.settings.DevConfig')

The db object is created in the models.py :

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

class MyClass(db.Model):
    ...

I would like the models.py to accommodate a variety of ORM and OGM (not limited to SQLAlchemy and py2neo) so that I can develop a Flask app to be SQL/Graph agnostic.

if __SOME_CONFIG__['db_mapper'] = 'SQLAlchemy':
    from flask_sqlalchemy import SQLAlchemy
    db = SQLAlchemy()
    class MapperModel(db.Model):
        ...
elif __SOME_CONFIG__['db_mapper'] = 'Py2Neo':

    from py2neo import Graph, Node, Relation
    db = Graph()
    class MapperModel(py2neo.Node):
        ...

class MyClass(MapperModel):
    ...

I can't see a way to use current_app to achieve this because I am creating my db object before the code is aware of an app object.

Is there a simple way to load the current configuration object from inside models.py ? Should I just load the configuration in models.py from a seperate file in the without reference to the app's current configuration object?

ChrisGuest
  • 3,398
  • 4
  • 32
  • 53

1 Answers1

1

Create a function which will return a db object, and initialize this object when you instantiate flask application:

app = create_app(...)
db = create_dbobject('someconfig')

def create_dbobject(someconfig):
    if someconfig == 'Py2Neo':
        return Py2Neo()
    #default to sqlchemy
    return SQLAlchemy()

So no more you have to worry about extension initialization. And its good to keep extensions initialization in place where app exists.

metmirr
  • 4,234
  • 2
  • 21
  • 34
  • Where do you suggest putting that piece of code? If I put it inside the `__init__.py` file, whenever I try to import from the package, the `app` and `db` objects get assigned automatically and it becomes a mess. Is there any way to handle this? – Kevin Jul 18 '18 at 05:32
  • You can still put it in the `__init__.py` file as `create_dbobject` function and in the `create_app` function call `create_dbobject` function to get db instance. But outside of the `create_app` function define `db = SQLAlchemy() # this is default ` in `create_app` function you can reassign it to Graph instance. Hence db instance is global and generic to your config you can use it without error. – metmirr Jul 18 '18 at 08:52
  • Makes sense. Any reason why you would want to assign the db outside? A better way would be to define `db = SQLAlchemy()` inside any file that needs it instead of importing it from the `__init__.py` file, no? – Kevin Jul 18 '18 at 09:57
  • This approach is good if you have sqlalchemy and graph as flask extensions. And you might want to use db instance from the shell. – metmirr Jul 18 '18 at 12:10