Flask project structures

Once you choose to follow Application Factory pattern which is officially recommended, the only place you could access app (the Flask() object) directly is inside create_app().

With the factory function, you are able to apply configurations dynamically which is particularly important for unit tests and CI.

$ tree simple-api
simple-api
├── Dockerfile
├── Pipfile
├── Pipfile.lock
├── app.py
├── requirements.txt
└── simple_api
    ├── bar
    │   ├── __init__.py
    │   ├── endpoints.py
    │   └── tasks.py
    ├── foo
    │   ├── __init__.py
    │   ├── endpoints.py
    │   └── tasks.py
    ├── __init__.py
    ├── config.py
    └── tasks.py
# simple_api/config.py
import os

class Config(object):
    SECRET_KEY = 'secret-key'

class ProductionConfig(Config):
    pass

class DevelopmentConfig(Config):
    pass
# simple_api/__init__.py
from flask import Flask, request
from flask_caching import Cache
from flask_mongoengine import MongoEngine

cache = Cache()
db = MongoEngine()

def init_cache(app, cache):
    cache.init_app(app, config={
        'CACHE_TYPE': 'redis',
        'CACHE_REDIS_URL': app.config['CACHE_REDIS_URL'],
    })

def init_db(app, db):
    db.init_app(app)

def create_app(env='production'):
    configs = {
        'production': 'simple_api.config.ProductionConfig',
        'development': 'simple_api.config.DevelopmentConfig',
    }

    app = Flask(__name__)
    app.config.from_object(configs[env])

    init_cache(app, cache)
    init_db(app, db)

    from . import foo
    from . import bar
    app.register_blueprint(foo.bp)
    app.register_blueprint(bar.bp)

    @app.errorhandler(404)
    def page_not_found(exc):
        return f'Page not found: {request.path}', 404

    @app.route('/')
    def health():
        return 'OK'

    return app
# simple_api/foo/__init__.py
from flask import Blueprint

foo_bp = Blueprint('foo', __name__, url_prefix='/foo')

# modules are imported at the bottom to avoid errors due to circular dependencies
from . import endpoints, tasks
# app.py
import simple_api

app = simple_api.create_app()

@app.cli.command()
@click.argument('name')
def hello(name):
    print(f'Hello {name}')
$ FLASK_APP=app.py FLASK_ENV=development flask run

If you don't want to use Application Factory pattern, you could just initialize app and import it in your endpoints.py.

# simple_api/__init__.py
from flask import Flask

app = Flask(__name__)

# modules are imported at the bottom to avoid errors due to circular dependencies
from . import endpoints
# simple_api/endpoints.py
from . import app

@app.route('/')
def health():
    return 'OK'

folder structure
http://flask.pocoo.org/docs/1.0/tutorial/layout/
http://flask.pocoo.org/docs/1.0/tutorial/factory/
https://www.safaribooksonline.com/library/view/flask-web-development/9781491991725/ch07.html

application factory
http://flask.pocoo.org/docs/1.0/patterns/appfactories/
http://flask.pocoo.org/docs/1.0/patterns/packages/

blueprint
http://flask.pocoo.org/docs/1.0/tutorial/views/
http://flask.pocoo.org/docs/1.0/blueprints/

circular imports
http://flask.pocoo.org/docs/1.0/patterns/packages/#working-with-blueprints
https://www.safaribooksonline.com/library/view/flask-web-development/9781491991725/ch07.html#ch_large