4
votes

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.

1

1 Answers

6
votes

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.