Feyzi Bagirov
Feyzi Bagirov

Reputation: 1372

Blueprints in Flask

I am taking over a Flask application that has a user module, but does not have a landing page. The structure of the project is:

|-application.py
|-manage.py
|-settings.py
|-/templates
|----base.html
|----index.html
|----navbar.html
|----/user
|--------views.py

application.py:

from flask import Flask

....

def create_app(**config_overrides):
    app = Flask(__name__)
    app.config.from_pyfile('settings.py')

    app.config.update(config_overrides)

    db.init_app(app)

    from user.views import user_app
    app.register_blueprint(user_app)

    return app

user/views.py:

from flask import Blueprint, render_template, request, redirect, session, url_for, abort
...

user_app = Blueprint('user_app', __name__)

@user_app.route('login', methods = ('GET','POST'))
def login():
  ....

I placed index.html in the templates folder.

Should I place a view.py in the root directory where I would put a route to an index.html?

Upvotes: 3

Views: 2403

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1121168

You can add additional routes anywhere you want.

However, since the package uses a create_app() app factory, you can't register those routes with an @app.route() decorator; the app is not created in a way you can just import.

So yes, creating a views.py module is a good organisational idea, but do create a Blueprint() there too, and register that blueprint in the create_app() function with the Flask() app instance.

In views.py:

from flask import Blueprint

bp = Blueprint('main', __name__)

@main.route('/')
def index():
    # produce a landing page

and in create_app() in application.py, add

import views
app.register_blueprint(views.bp)

(I use a convention of using the bp variable name for all my blueprints, and then just importing the module and registering the module.bp attribute).

It's the explicit import and app.register_blueprint() call that ties any of the blueprints used in a Flask project into the final app's routes. Blueprints can share the same prefix, including having no prefix.

One thing to note: here the views module is now a top-level module next to application.py. It'd be better if everything was moved into a package, giving you more freedom over what names you use. All modules in a single package are namespaced, kept separate from other top-level modules such as json and time and flask, so there won't be clashes when you want to use the same name for one of the additional modules in your project.

You'd move everything but manage.py into a subdirectory, with a project-appropriate name, and move application.py to __init__.py. Imports can then use from . import ... to import from the current package, etc.

Upvotes: 3

Related Questions