stef
stef

Reputation: 27789

Flask ImportError

Taking my first steps with Flask and python in general. I'm trying to build a very basic app using Flask-Admin to build a Model View page.

All the code samples from the Flask and Flask-Admin run as they should and the ModelView can run basic CRUD on my database.

But, when I use a separate models.py file (from this tutorial), things go wrong.

app.py

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_admin import Admin
from flask_admin.contrib.sqla import ModelView

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = "sqlite:///database/db.db"
app.config['FLASK_ADMIN_SWATCH'] = 'flatly'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)

from models import *

class PostView(ModelView):
    edit_modal = True

admin = Admin(app, name='ProjectX', template_mode='bootstrap3')
admin.add_view(PostView(Post, db.session))
if __name__ == '__main__':
    app.run()

models.py

from app import db

class Post(db.Model):
    __tablename__ = 'post'

    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(255), unique=True, nullable=False)
    text = db.Column(db.String(255), unique=False, nullable=False)

    def __repr__(self):
    return '<Post {}>'.format(self.title)

When I run python app.py I get:

Traceback (most recent call last):
  File "app.py", line 12, in <module>
    from models import *
  File "/Users/me/Sites/projectx/models.py", line 1, in <module>
    from app import db
  File "/Users/me/Sites/projectx/app.py", line 18, in <module>
    admin.add_view(PostView(Post, db.session))
NameError: name 'Post' is not defined

When I change from models import * to from models import Post I get

Traceback (most recent call last):
  File "app.py", line 12, in <module>
    from models import Post
  File "/Users/me/Sites/projectx/models.py", line 1, in <module>
    from app import db
  File "/Users/me/Sites/projectx/app.py", line 12, in <module>
    from models import Post
ImportError: cannot import name 'Post'

It seems to me that db is not available in models.py? Is this a problem with circular imports and if so, how can I fix this?

EDIT I may have messed some things up wrt my virtual environments (I think I have both pipenv and autoenv running) and there's some confusion with pip / python2 / python3. But I doubt this has anything to do with the problem. This app definitely runs on 3.6.5

Upvotes: 0

Views: 804

Answers (1)

Dave W. Smith
Dave W. Smith

Reputation: 24966

You're worked your way in to something called "the circular import problem." In this case, it happens like this.

Python begins parsing/evaluating app.py. Midway in, it finds from models import * (or one of the other variants you tried).

The parsing/evaluating of app.py is temporarily suspended to pull in symbols from models.

Python begins parsing/evaluating models.py, and immediately encounters from app import db.

For very slightly convoluted (but sensible) reasons, Python then wants to complete the parsing/evaluating of app.py, but when it does, it encounters the reference to Post, which hasn't yet been defined because the parsing/evaluating of models.py was suspended. Python then raises a NameError.

The easiest way I know to resolve this it to create a separate views.py, which would look something like

from app import admin, db
from models import Post
from flask_admin.contrib.sqla import ModelView

class PostView(ModelView):
    edit_modal = True
admin.add_view(PostView(Post, db.session)

then import it at the end of app.py after you've imported models.

Upvotes: 2

Related Questions