Flask - Attempted relative import in non-package - flask

Following this tutorial on how to structure a Flask app, I have:
project/
__init__.py
app.py
models/
__init__.py
base.py
base.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
models/__init__.py
from .base import db
def init_app(app):
db.init_app(app)
project/__init__.py
from flask import Flask
def create_app()
from . import models, routes, services
app = Flask(__name__)
models.init_app(app)
# routes.init_app(app)
# services.init_app(app)
return app
finally, in app.py, I try to run it:
from . import create_app
app = create_app()
if __name__ == '__main__':
app.run(use_reloader=True, threaded=True, debug=True)
but I'm getting the error:
from . import create_app
ValueError: Attempted relative import in non-package
Am I building it right, what am I doing wrong?

I guess you are running your program by:
python project/app.py
In this case, you are not treat your "project" as a python package, which will raise the error you got. Instead, you can run your project with:
FLASK_APP=project.app flask run

Related

How to determine flask_app name

Sorry if this is a bit basic but wanted to validate what my flask_app name would be that I set in my .env file when running locally.
I run my app using a wsgi.py file in root with the following contents:
from app import create_app, db
application = create_app()
if __name__ == '__main__':
application.run()
However I then have a app/init.py
import os
from config import Config
from flask import Flask, render_template
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
def create_app(config_class=Config):
app = Flask(__name__)
app.config.from_object(config_class)
#not sure if i mucked this up
db.init_app(app)
from app.main import main_blueprint
app.register_blueprint(main_blueprint)
return app
Which I run with flask run. Therefore is my app name “app” or “application” or even something else?
You want flask_app variable to be the name of the file which runs the app, so for you in your .env file it looks like you should have:
FLASK_APP = run.py
where run.py is the name of the file containing the first block of code in your question, assuming that your .env file is also in your root folder, let me know if that helps.

Flask - How to load database with config from Flask config?

My folder structure is the following:
- app.py
app
- __init__.py
- database.py
in app.py I have:
from app import create_app
app = create_app()
my init.py looks something like:
from flask import Flask
from app.database import db_session, init_db
db = SQLAlchemy()
def create_app():
myapp = Flask(__name__, static_folder='static', static_url_path='/static', template_folder="templates")
myapp.config.from_object('config.Config')
db.init_app(myapp)
migrate.init_app(myapp, db)
# loading blueprints
from app.core_bp import core_bp
myapp.register_blueprint(core_bp, url_prefix='/', template_folder="templates")
return myapp
and database.py looks like this
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
engine = create_engine('sqlite:///rapporteur.db')
db_session = scoped_session(sessionmaker(autocommit=False,autoflush=False,bind=engine))
That sqlite path is currently hardcoded to raporteur.db but it should be loaded from config, because I don't want it hardcoded, but unfortunately the flask app is not yet loaded. So how would I do this?
You can use flask-sqlalchemy and set the SQLALCHEMY_DATABASE_URI in the config file.
class Config:
SQLALCHEMY_DATABASE_URI = 'sqlite:///rapporteur.db'
then in your init.py
from youApp import Config
def create_app(config_class=Config)
app = Flask(__name__)
app.config.from_object(config_class)
db = SQLAlchemy()
db.init_app(app)
return app

Flask __init__.py structure on Heroku

from .library.routes import library
2022-05-25T11:06:23.522123+00:00 app[web.1]: ImportError: attempted relative import with no known parent package
This is the log shown by heroku, and I encountered this problem again and again and again.
How could I solve this and deploy my site on heroku?
init.py
from flask import Flask
from .library.routes import library
from .chat.routes import chat
from .extensions import db, bcrypt, login, socketio
from .api.library_api import library_api
from .api.chat_api import chat_api
from .models.chat import user
from .user.routes import user_route
from .api.login_api import login_api
from .api.socket_api import socket_api
def create_app():
app = Flask(__name__)
app.secret_key = "Why would I show it to stackoverflow?"
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///library.sqlite3"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
app.config["SQLALCHEMY_BINDS"] = {
'chat': "sqlite:///chat.sqlite3",
"library": "sqlite:///library.sqlite3"
}
db.init_app(app)
bcrypt.init_app(app)
login.init_app(app)
socketio.init_app(app)
login.blueprint_login_views = {
'chat': '/login',
'library': '/login'
}
with app.app_context():
db.create_all()
app.register_blueprint(library)
app.register_blueprint(chat)
app.register_blueprint(library_api)
app.register_blueprint(chat_api)
app.register_blueprint(user_route)
app.register_blueprint(login_api)
app.register_blueprint(socket_api)
return app
Procfile
web: gunicorn __init__:app --log-file=-
web: gunicorn --worker-class eventlet -w 1 __init__:app
This init.py is really hindering my development (especially when it comes to debugging due to it running 1000% slower than using a one big app.py) but I want to keep the blueprint approach for ease of organization

flask NoAppException but flask run works

I have the following structure:
app_dir/
| myapi/
| __init__.py
| myapi_app.py
where myapi_app.py is
from myapi import create_app, db
app = create_app()
and myapi/__init__.py is
import logging
import os
from logging.handlers import RotatingFileHandler
from flask import Flask, request, current_app
from flask_sqlalchemy import SQLAlchemy
from myapi.config import Config
db = SQLAlchemy()
def create_app(config_class=Config):
app = Flask(__name__)
app.config.from_object(config_class)
db.init_app(app)
...
return app
When I set FLASK_APP=myapi_app.py and run flask run from the app_dir directory, the flask service starts. However, when I make a request, I get the following error: flask.cli.NoAppException: Could not import "myapi_app". Where am I going wrong?
Your problem is that you are setting $FLASK_APP to the file in which the app variable is stored, you should instead set it to the python object path, e.g.
FLASK_APP=myapi_app:app
However, this is not necessary, as you could also just do:
FLASK_APP=myapi
as Flask will look for a create_app function in the package on its own.

In Flask is it possible to import views using the create_app() pattern without using Blueprints?

I have a very small Flask app that is laid out as follows:
tinker/
main.py
/my_package
init.py
views.py
When I do tinker>python main.py everything runs fine. Here are the contents of each file:
main.py:
from my_package import app
app.run()
my_package/init.py:
from flask import Flask
app = Flask(__name__)
from my_package import views
my_package/views.py:
from my_package import app
#app.route('/')
def home():
return 'Ola!!!!!'
While all the above code runs fine when I try to modify it slightly by using a a create_app() code pattern, as in the below, views.py throws the following exception: "ImportError: cannot import name 'app' from 'my_package' " Is there a way to fix the problem without using Blueprints?
main.py:
from my_package import create_app
app = create_app()
app.run()
my_package/init.py:
from flask import Flask
def create_app():
app = Flask(__name__)
from my_package import views
return app
my_package/views.py:
from my_package import app
#app.route('/')
def home():
return 'Ola!!!!!'
You import the views within application context, then in the views you can use current_app.
in mypackage/__init__.py:
def create_app():
app = Flask(__name__)
with app.app_context():
from . import views
in mypackage/views.py:
from flask import current_app
#current_app.route('/')
def index():
return 'hello, world!'
init.py needs to be renamed to __init__.py
Move app = Flask(__name__) outside of the create_app method
Change to from . import app in views.py