Everything was working fine, the imports have always worked and my project structure has not changed. I made some changes - adding fields & forms, and suddenly all the relative imports in my app/main/views.py stopped working. I reverted my changes - that did not work either. Help!
Update: So it runs fine from the command line with "flask run", but not in PyCharm. So I'm thinking it's PyCharm config issue. My config.py file has not changed at all, so I think it's here: PyCharm Run/Debug Config
I did not intentionally make ANY changes to the config.... so not sure what the next step is here. If anyone has advice on the config for this project, I would be grateful!
Here's the project structure. App, Auth and Main are shown as packages:
Project Structure
Here's the main app demo.py:
import os
from app import create_app, db
from app.models import Org, User, Role, DemoType, DemoReport, DemoRptQ, \
Demo, Question, Answer, Location
from flask_migrate import Migrate
app = create_app(os.getenv('FLASK_CONFIG') or 'default')
migrate = Migrate(app, db)
#app.shell_context_processor
def make_shell_context():
return dict(db=db, Org=Org, User=User, Role=Role, Location=Location,
DemoType=DemoType, DemoReport=DemoReport, DemoRptQ=DemoRptQ, Demo=Demo,
Question=Question, Answer=Answer)
#app.cli.command()
def test():
import unittest
tests = unittest.TestLoader().discover('tests')
unittest.TextTestRunner(verbosity=2).run(tests)
Here's the app init.py
from flask import Flask
from flask_bootstrap import Bootstrap
from flask_mail import Mail
from flask_moment import Moment
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
from config import config
bootstrap = Bootstrap()
mail = Mail()
moment = Moment()
db = SQLAlchemy()
login_manager = LoginManager()
login_manager.login_view = 'auth.login'
def create_app(config_name):
app = Flask(__name__)
app.config.from_object(config[config_name])
config[config_name].init_app(app)
bootstrap.init_app(app)
mail.init_app(app)
moment.init_app(app)
db.init_app(app)
login_manager.init_app(app)
from .main import main as main_blueprint
app.register_blueprint(main_blueprint)
from .auth import auth as auth_blueprint
app.register_blueprint(auth_blueprint, url_prefix='/auth')
return app
And the app/main package init.py:
from flask import Blueprint
main = Blueprint('main', __name__)
from . import views, errors
from ..models import Permission
#main.app_context_processor
def inject_permissions():
return dict(Permission=Permission)
And finally the app/main views.py, where I am getting the error on the third line from .. import db
from datetime import datetime
from flask import render_template, session, redirect, url_for, flash
from .. import db
from ..models import User, Role, Location, Demo, Question, Answer, DemoType, DemoReport, DemoRptQ
from ..email import send_email
from . import main
from .forms import DashboardForm, EditProfileForm, EditProfileAdminForm, DemosForm, DemoForm
from .forms import QuestionsForm, QuestionForm, DemoTypesForm, DemoTypeForm, DemoReportsForm, DemoReportForm
from .forms import AnswerForm, AnswersForm, LocationsForm, LocationForm
from .forms import UsersForm
from flask_login import login_required, current_user
from ..decorators import admin_required
from wtforms.validators import DataRequired, Optional, Length
#main.route('/', methods=['GET', 'POST'])
def index():
form = DashboardForm()
if form.validate_on_submit():
btn = form.submit.raw_data[0]
if btn == 'Demos':
return redirect(url_for('.demos_list'))
elif btn == 'New Demo':
return redirect(url_for('.edit_demo', id=0))
elif btn == 'Login':
return redirect(url_for('auth.login'))
elif btn == 'Register':
return redirect(url_for('auth.register'))
return render_template('index.html', form=form, isauth=current_user.is_authenticated)
#main.route('/users')
def users_list():
form = UsersForm()
if form.validate_on_submit():
return redirect(url_for('.index'))
I found this answer in another post and it worked! In Pycharm Run/Debug Configs, uncheck "Add Content Roots to PYTHONPATH" and "Add Source Roots to PYTHONPATH". Don't understand why it broke or why it's fixed... but there's plenty of time for that later.
PyCharm Config Fix
I see below error even after setting secret_key, unable to figure out what i'm missing here please advice
Error:
RuntimeError: The session is unavailable because no secret key was set. Set the secret_key on the application to something unique and secret.
Code below
config.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
#from .models import db
db = SQLAlchemy()
def create_app():
app = Flask(__name__)
app.config['secret_key'] = '\x90vv\xdd\x11?<\xbf \xd3\xb2\xab\x12\xb5\xa3\xee'
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://postgres:admin#localhost:5432/WebApp'
db.init_app(app)
login_manager = LoginManager()
login_manager.login_view = 'auth.login'
login_manager.init_app(app)
from .models import Person
#login_manager.user_loader
def load_user(user_id):
return Person.query.get(int(user_id))
from .auth import auth as auth_blueprint
app.register_blueprint(auth_blueprint)
return app
There are a few ways of setting a secret key for Flask application.
Using app.config, the SECRET_KEY part must be uppercase here which is why you're receving an error:
app.config['SECRET_KEY'] = 'my-secret-key'
Using Flask application object:
app.secret_key = 'my-secret-key'
More information can be found in Flask documentation: https://flask.palletsprojects.com/en/1.1.x/api/#flask.Flask.secret_key
I was trying to create a new user from the terminal using flask fab but when I run the command and fill all the required info like username, email, password I get this error message: AttributeError: 'Flask' object has no attribute 'appbuilder'.
Full traceback:
https://pastebin.com/gACSfChG
FLASK_APP=run.py
run.py
import os
from app import RubyAPP
config_name = os.getenv('FLASK_CONFIG')
app = RubyAPP(config_name).app()
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0')
__init__.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_login import LoginManager
from flask_login import current_user
from flask import render_template
db = SQLAlchemy()
app = Flask(__name__, instance_relative_config=True)
login_manager = LoginManager(app)
#app.errorhandler(404)
def not_found_404(e):
return render_template('404.html'), 404
class RubyAPP(object):
def __init__(self, config_name):
# App manager
app.config.from_pyfile('config.py')
db.init_app(app)
# Login manager
login_manager.init_app(app)
login_manager.login_message = 'You must be logged in to access this page'
login_manager.login_view = 'auth.login'
# Flask migrate
migrate = Migrate(app, db)
def app(self):
# Error handling apps registers
app.register_error_handler(404, not_found_404)
# Models
from app import models
# Views
from .home import home as home_blueprint
app.register_blueprint(home_blueprint)
from .profile.links import links as links_blueprint
app.register_blueprint(links_blueprint)
from .login import login as login_blueprint
app.register_blueprint(login_blueprint)
return app
I tried reinstalling appbuilder but gives the same error. I think these 2 files are enough but since I don't know whats giving the error let me know if you need any extra file.
Had the same error. You have to run appbuilder.init_app() for your app:
..
..
class RubyAPP(object):
def __init__(self, config_name):
# App manager
app.config.from_pyfile('config.py')
db.init_app(app)
with app.app_context():
appbuilder.init_app(app, db.session)
..
..
I created a Flask app with SQLAlchemy.
I initialised the database in app.py but I want to use it in another file: otherfile.py.
app.py
app = Flask(__name__)
app.config['JSONIFY_PRETTYPRINT_REGULAR'] = True
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///my_database'
db = SQLAlchemy(app)
print("TEST")
otherfile.py
from app import db
print(db)
But I get the error.
ImportError: cannot import name 'db'
Basically, I am doing this because I do not want to write the SQLAlchemy logic in app.py but I want to keep it in another file.
In addition, I just want the variable db to be exported. I do not want that when I run otherfile.py, this runs also print("TEST") which is in app.py
I looked at these answer with little luck:
How to share the global app object in flask?
Split Python Flask app into multiple files
How to divide flask app into multiple py files?
The SQLAlchemy class doesn't need to receive the app param on its initialization. So what you can do is create the db object in your otherfile.py and import it in app.py, where you can pass it the app object with SQLAlchemy.init_app().
app.py
from flask import Flask
from otherfile import db
app = Flask(__name__)
app.config['JSONIFY_PRETTYPRINT_REGULAR'] = True
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///my_database'
db.init_app(app)
otherfile.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
I have the following project structure:
project/__init__.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
db = SQLAlchemy()
migrate = Migrate()
def create_app():
app = Flask(__name__)
app.config.from_object(os.environ['APP_SETTINGS'])
db.init_app(app)
migrate.init_app(app, db)
return app
run.py
from project import create_app
app = create_app()
if __name__ == "__main__":
app.run()
manage.py
from flask_script import Manager
from flask_migrate import MigrateCommand
from project.models import *
from project import create_app
manager = Manager(create_app)
manager.add_command('db', MigrateCommand)
if __name__ == '__main__':
manager.run()
Yet when I run the following commands, Flask-Migrate is not detecting any tables to be added.
python manage.py db init
Which outputs:
Creating directory $HOME/Project/migrations ... done
Creating directory $HOME/Project/migrations/versions ... done
Generating $HOME/Project/migrations/script.py.mako ... done
Generating $HOME/Project/migrations/env.py ... done
Generating $HOME/Project/migrations/README ... done
Generating $HOME/Project/migrations/alembic.ini ... done
Please edit configuration/connection/logging settings in
'$HOME/Project/migrations/alembic.ini' before proceeding.
and
python manage.py db migrate
Which only outputs:
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
Why is Flask-Migrate with Alembic not detecting the Models and therefore creating the tables? Here's what I've tried:
Deleting the database, starting from nothing
Creating a custom db class inside the manage.py file, doesn't detect that
Googling every answer to this problem, found lots of similar questions but none of their solutions worked for me.
EDIT:
Here is an example of the models.py file
from flask import current_app
from project import db
from flask_login import UserMixin
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50))
The solution was to import the models in the __init__.py file like so:
def create_app():
app = Flask(__name__)
app.config.from_object(os.environ['APP_SETTINGS'])
from project import models
db.init_app(app)
migrate.init_app(app, db)
return app
I had the same issue. The solution is pretty same as #joe's
In routes file
from models import User
api_user = Namespace('user', description='user related operations')
In project/__init__.py
def create_app():
app = Flask(__name__)
app.config.from_object(os.environ['APP_SETTINGS'])
from project import models
db.init_app(app)
migrate.init_app(app, db)
blueprint = Blueprint('api', __name__, url_prefix=url_prefix)
api = Api(blueprint, doc='/documentation') # ,doc=False
app.register_blueprint(blueprint)
api.add_namespace(api_user)
return app
when adding api_user namespace in create_app flask_migrate detected models