'Blueprint and factory pattern work together?
I am working on a restful service using flask-restful, and I want to leverage both factory pattern and blueprint in my project.
in app/__init__.py
I have a create_app
function to create a flask app and return it to outside caller, so the caller can start the app.
def create_app():
app = Flask(__name__)
app.config.from_object('app.appconfig.DevelopmentConfig')
from app.resource import resource
app.register_blueprint(v1, url_prefix='/api')
print app.url_map
return app
Inside that function I intended to register a blueprint pointing to the implementation package with a prefix url.
In app/resource/__init__.py
there is the following code:
from flask import current_app, Blueprint, render_template
from flask.ext import restful
resource = Blueprint('resource', __name__, url_prefix='/api')
@resource.route('/')
def index():
api = restful.Api(current_app)
from resource.HelloWorld import HelloWorld
api.add_resource(HelloWorld, '/hello')
My goal is that I can access the HelloWorld rest service at url /api/hello
, but I know the above code has something wrong at part of @resource.route('/') ...
. I got some error like AssertionError: A setup function was called after the first request was handled. This usually indicates a bug in the app ...
at api.add_resource(HelloWorld, '/hello')
.
Could you please give me some hints on the correct approach?
Solution 1:[1]
Flask-Restful, like all properly implemented Flask extensions, supports two methods of registering itself:
- With the app at instantiation (as you are trying to do with
Api(current_app)
) - At a later point using
api.init_app(app)
The canonical way of dealing with the circular imports issue is to use the second pattern and import the instantiated extension in your create_app
function and register the extension using the init_app
method:
# app/resource/__init__.py
from resource.hello_world import HelloWorld
api = restful.Api(prefix='/api/v1') # Note, no app
api.add_resource(HelloWorld, '/hello')
# We could actually register our API on a blueprint
# and then import and register the blueprint as normal
# but that's an alternate we will leave for another day
# bp = Blueprint('resource', __name__, url_prefix='/api')
# api.init_app(bp)
And then in your create_app
call you would simply load and register the api:
def create_app():
# ... snip ...
# We import our extension
# and register it with our application
# without any circular references
# Our handlers can use `current_app`, as you already know
from app.resource import api
api.init_app(app)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Sean Vieira |