Search code examples
pythonflaskpackageimporterrorproject-structure

Python / Flask App - Relative Imports Stopped Working


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'))


Solution

  • 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