I want to have several app factories(currently: one for development, and another one for testing). I am wondering what is the proper way to implement them.
Currently I use app object to register views(via @app.route()
decorator). Do I need to start using blueprints(instead of app) to register views? Is there any way to have proper app factories without blueprients?
Each Flask Blueprint is an object that works very similarly to a Flask application. They both can have resources, such as static files, templates, and views that are associated with routes. However, a Flask Blueprint is not actually an application. It needs to be registered in an application before you can run it.
Blueprints can simplify how large applications work and also provide a central means for Flask extensions to register operations on applications. It also works in a way to extend existing Flask applications. A Blueprint object works similarly to a Flask application object, but it is not actually an application.
Although Flask has a built-in web server, as we all know, it's not suitable for production and needs to be put behind a real web server able to communicate with Flask through a WSGI protocol. A common choice for that is Gunicorn—a Python WSGI HTTP server.
technically, you don't need blueprints, you can just register each route on your create_app
function. Generally speaking that's not a great idea, and it's kind of why blueprints exist.
Example without blueprints
def create_app():
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
return app
You can have a single app factory for both testing and whatever else if you configure it that way. If you want to load different blueprints based on if it is in testing, you can do something like this.
from project.config import configurations as c
def create_app(config=None):
" make the app "
app = Flask(__name__)
app.config.from_object(c.get(config, None) or c['default'])
configure_blueprints(app)
return app
def configure_blueprints(app):
" register the blueprints on your app "
if app.testing:
from project.test_bp import bp
app.register_blueprint(bp)
else:
from project.not_test_bp import bp
app.register_blueprint(bp)
then project/config.py
could be like this:
class DefaultConfig(object):
PROJECT_NAME = 'my project'
class TestingConfig(DefaultConfig):
TESTING = True
class DevConfig(DefaultConfig):
DEBUG = True
configurations = {
'testing': TestingConfig,
'dev': DevConfig,
'default': DefaultConfig
}
Make a folder for each blueprint where the __init__.py
in the folder instantiates the blueprint. Let's say for a blueprint called routes
from flask import Blueprint
bp = Blueprint('routes', __name__)
from project.routes import views
then in project/routes/views.py
, you can put your views.
from project.routes import bp
@bp.route('/')
def index():
return render_template('routes/index.html')
You surely can have application factory without the blueprint, but that often makes no sense.
Assuming you have an application package called myapp
.
Here is your __init__.py
:
from flask import Flask
def create_app():
app = Flask(__name__)
return app
Now we create a new .py
file called autoapp.py
(or wsgi.py
or manage.py
etc.) outside of myapp
package. In the autoapp.py
, you create the application instance and import the views from myapp
:
from myapp import create_app
app = create_app()
from myapp import views
The import statement will link the app
with your routes. You can import app
in your views.py
like this:
from autoapp import app
@app.route('/')
def index():
return 'Hello!'
The application structure:
myapp/
myapp/
__init__.py
views.py
autoapp.py
For those who googled this question. You don't have to use blueprints. Just import current_app as app in your routes.py (or views.py, whatever) and you are free to go.
from flask import current_app as app
Also, you have to add this to the factory (the create_app function) to register your routes:
with app.app_context():
from . import routes
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With