Using flask-restful, i can not import the object mongo = PyMongo()
from the file app/__init__.py
into app/common/db.py
.
My folder structure looks like this:
myproject/
run.py
app/
__init__.py
config.py
common/
__init__.py
db.py
auth/
__init__.py
resources.py
app/__init__.py contains:
from flask import Flask, Blueprint
from flask_pymongo import PyMongo
from flask_restful import Api
from app.config import Config
from app.auth.resources import Foo
mongo = PyMongo()
bp_auth = Blueprint('auth', __name__)
api_auth = Api(bp_auth)
api_auth.add_resource(Foo, '/foo/<string:name>')
def create_app(config_class=Config):
app = Flask(__name__)
app.config.from_object(config_class)
mongo.init_app(app)
app.register_blueprint(bp_auth)
return app
app/common/db.py contains:
from app import mongo
the application itself is run from the root via run.py which contains:
from app import create_app
app = create_app()
if __name__ == '__main__':
app.run(debug=True)
Problem:
Running the application i get an ImportError:
from app import mongo
ImportError: cannot import name 'mongo'
Why this is not working?
Thanks for your help!
EDIT:
Full Traceback:
Traceback (most recent call last):
File "run.py", line 1, in <module>
from app import create_app
File "/home/bt/Dropbox/dev/flask/test_api/app/__init__.py", line 13, in <module>
from app.auth.resources import SignIn, Users, User, Foo
File "/home/bt/Dropbox/dev/flask/test_api/app/auth/resources.py", line 8, in <module>
from app.common.resources import AuthResource
File "/home/bt/Dropbox/dev/flask/test_api/app/common/resources.py", line 3, in <module>
from app.auth.decorators import token_required
File "/home/bt/Dropbox/dev/flask/test_api/app/auth/decorators.py", line 6, in <module>
from app.common.database import users
File "/home/bt/Dropbox/dev/flask/test_api/app/common/database.py", line 1, in <module>
from app import mongo
ImportError: cannot import name 'mongo'
As I suspected, this is a circular import problem.
You can track the closed loop of dependencies looking at the traceback:
app -> resources -> database -> app
This is a common mistake and not properly documented in Flask tutorials. As explained here by Lepture, you should avoid declaring db in the __init__.py
I always keep this one certain rule when writing modules and packages:
Don't backward import from root
__init__.py
.
How should you do it, then?
db.py
)I found myself reluctant towards this pattern, I thought those import
statements didn't belong inside a function. But this is the way to go.
So, your files should look something alike:
app/common/db.py
from flask_pymongo import PyMongo
mongo = PyMongo
app/__init__.py
from flask import Flask
...
def create_app(config_class=Config):
app = Flask(__name__)
app.config.from_object(config_class)
from app.common.db import mongo
mongo.init_app(app)
...
and when you need your database connection, i.e. in resources module, you should import it like
from app.common.db import mongo
Note: to avoid future problems, your blueprints should also be declared elsewhere and import on creation time. I really encourage you to read the post by Lepture to better understand this approach.