Reputation: 27789
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
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