Here is what I'm working with:
/myproject
README.md
runserver.py
/myproject
__init__.py
api.py
/resources
__init__.py
foo.py
bar.py
/common
__init__.py
db.py
/tests
test_myproject.py
Nothing special here. Most of this can be found on the Intermediate Usage page in the Flask-RESTful User's Guide.
My concern is with circular imports...
api.py
from flask import Flask
from flask_restful import Api
app = Flask(__name__)
from myproject.resources.foo import Foo
from myproject.resources.bar import Bar
api = Api(app)
api.add_resource(Foo, '/Foo', '/Foo/<str:id>')
api.add_resource(Bar, '/Bar', '/Bar/<str:id>')
foo.py
from flask_restful import Resource
from myproject.common.db import query_db
class Foo(Resource):
def get(self):
pass
def post(self):
pass
db.py
from flask import g
import sqlite3
from myproject.api import app
def get_db():
db = getattr(g, '_database', None)
if db is None:
db = g._database = sqlite3.connect(app.config['DATABASE'])
db.row_factory = make_dicts
return db
def query_db(query, args=(), one=False):
cur = get_db().execute(query, args)
rv = cur.fetchall()
cur.close()
return (rv[0] if rv else None) if one else rv
@app.teardown_appcontext
def close_connection(exception):
db = getattr(g, '_database', None)
if db is not None:
db.commit()
db.close()
Clearly, I have introduced a circular import into my project:
api.py -> foo.py -> db.py -> api.py
This isn't a big problem as long as I instantiate the Flask application object before I import my resources (which I do). A similar pattern is discussed here (see the Circular Imports section at the bottom of the page).
My question...
Is this a good way to structure a Flask-RESTful project?
This is the closest SO question on this topic that I could find. I was not satisfied with the answer provided because I don't want to keep my database functions in the top level __init__.py
file (or in api.py
- where the routes belong).
Here are several other similar SO questions, but they are dealing with import errors (which I am not):
Since your question is largely opinion based, I'm going to suggest what I think would be a better solution :)
Instead of importing
myproject.api.app
indb.py
, I would create my own module level global variable indb.py
to store database configuration:db.py
Then in
api.py
initialize db by callingmyproject.common.db.init()
api.py
This way
db.py
no longer has a dependency onapi.py