Python clean imports for models - SQL Alchemy

flask, flask-sqlalchemy, python

Solution

1st approach:

I've ended up with the following structure:

- project_root — also holds some configs, .gitignore file, etc

- start.py

- flask_root

- __init__.py

- application.py

- module_1

- __init__.py

- models.py

- module_2

- __init__.py

- models.py

Topmost start.py just runs the app:

#! /usr/bin/env python
from flask_root import applicaiton

if __name__ == '__main__':
    application.manager.run()

Python searches for packages in the directory you script started from, so now you don't need add them to sys.path (as for me, modification of sys.path looks ugly). Now you have full-working flask_root python package, and you can import everything from it, from any place of your application:

from flask_root.application import db

2nd approach:

If you start your Flask application from it's directory,

./application.py runserver

the directory you've started from is not be accessible as python package, even if it has __init__.py in it.

Though, with your directory layout you can do the following trick:

models/__init__.py:

from application import db
...

models/user.py:

from . import db
...

The first approach is more clean and universal. The second possibly can be useful when you need to share same blueprints between multiple Flask projects.

Problem

I have a flask app with the following directory structure: - myapp/ - application.py - `__init__.py` - models/ - `__init__.py` - user.py The models use Flask-SQLAlchemy, and therefore, they need to have access to the `db` object (a SQLAlchemy instance) from `application.py` user.py: ``` import sys,os sys.path.append('/path/to/application/package') from testapp import db class User(db.Model): id = db.Column(db.Integer,primary_key=True) username = db.Column(db.String(255),unique=True) age = db.Column(db.Integer) def __init__(self,username,age): self.username = username self.age = age def __repr__(self): return '<User %r>' % self.username ``` Because any of the models need access to the application's SQLAlchemy instance, the `db` property, I have to throw this whole package on the path and then import from the main application module. For sanity's sake, I would like to keep the models in separate files. Will I need to put the path code on top of every model? Is there a better way? I'd rather not have the full path input like that, as they may be deployed to different hosts with different directory structures. Ideally there would be some way to internally handle the path so when it is used as another user via `mod_wsgi` I don't have to manually change the code.

Original source