Search code examples
pythonflaskherokuflask-sqlalchemy

Deploying Postgres Flask App on Heroku, "gunicorn.errors.AppImportError: Failed to find attribute 'app' in 'app'."


I've been trying to deploy my Flask app to Heroku for over a day, watching/reading several tutorials, and digging through all the stackoverflow questions i could find and still haven't found a solution for my issue. When i deploy my app, I get the error "gunicorn.errors.AppImportError: Failed to find attribute 'app' in 'app'." I've changed my Procfile many times to get heroku to run my app but i always get the same error.

This is how my app is structured: enter image description here

My Procfile includes this statement:

web: gunicorn app:app --preload

I am thinking my issues could be how im creating my app, but could not find a solution. My main app file looks like this:

from venv import create
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from os.path import join, dirname, realpath
from flask_login import LoginManager

db = SQLAlchemy()

def create_app():
    app = Flask(__name__, static_folder='static')
    app.debug = True
    app.config['SECRET_KEY'] = 'abcde12568901fghij'
    #app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite3'
    app.config['SQLALCHEMY_DATABASE_URI'] = '[removed for privacy]'
    app.config['UPLOAD_DIRECTORY'] = join(dirname(realpath(__file__)), 'uploads/')
    app.config['MAX_CONTENT_LENGTH'] = 16*1024*1024 #16mb
    app.config['ALLOWED_EXTENSIONS'] = ['.jpg','.jpeg','.png','.gif','.mp4']

    db.init_app(app)

    login_manager = LoginManager()
    login_manager.login_view = 'auth.login'
    login_manager.init_app(app)

    from models import User

    @login_manager.user_loader
    def load_user(user_id):
        # since the user_id is just the primary key of our user table, use it in the query for the user
        return User.query.get(int(user_id))

    from auth import auth
    app.register_blueprint(auth)

    from views import main
    app.register_blueprint(main)

    return app

if __name__ == '__main__':
    db.create_all(app=create_app())

Screenshot of full logs: enter image description here

Any help would be greatly appreciated, thanks all!


Solution

  • app:app tells Gunicorn to look for a variable called app in your app.py file (strictly speaking, in your app module), but you don't have a variable with that name.

    Instead, you have a function create_app() that returns your app object. Gunicorn allows you to use that directly:

    The variable name can also be a function call. In that case the name will be imported from the module, then called to get the application object. This is commonly referred to as the "application factory" pattern.

    Update your Procfile accordingly:

    web: gunicorn 'app:create_app()' --preload