Skip to content

Instantly share code, notes, and snippets.

@Jaza
Last active March 10, 2024 18:26
Show Gist options
  • Save Jaza/61f879f577bc9d06029e to your computer and use it in GitHub Desktop.
Save Jaza/61f879f577bc9d06029e to your computer and use it in GitHub Desktop.
Example of how to split a Flask blueprint into multiple files, with routes in each file, and of how to register all those routes.
"""
Note: can't put in a subdirectory for this example (GitHub Gists
doesn't allow subdirectories). Recommended to move this file to
foo/bar.py.
"""
routes = []
def ping_bar():
return 'Ping bar'
routes.append(dict(
rule='/ping-bar/',
view_func=ping_bar))
def save_bar():
return 'Save bar'
routes.append(dict(
rule='/save-bar/',
view_func=save_bar,
options=dict(methods=['POST',])))
"""
Note: can't put in a subdirectory for this example (GitHub Gists
doesn't allow subdirectories). Recommended to move this file to
foo/baz.py.
"""
routes = []
def call_baz():
return 'Call baz'
routes.append(dict(
rule='/call-baz/',
view_func=call_baz))
def delete_baz():
return 'Delete baz'
routes.append(dict(
rule='/delete-baz/',
view_func=delete_baz,
options=dict(methods=['GET', 'POST'])))
from flask import Flask
app = Flask(__name__)
app.debug = True
@app.route('/')
def home():
return 'App home'
from foo import mod
app.register_blueprint(mod, url_prefix='/foo')
if __name__ == '__main__':
app.run()
"""
Note: can't put in a subdirectory for this example (GitHub Gists
doesn't allow subdirectories). Recommended to move this file to
foo/__init__.py, and to change the imports to
'from .bar' and 'from .baz'.
"""
from flask import Blueprint
mod = Blueprint('foo', __name__)
@mod.route('/')
def home():
return 'Foo home'
from bar import routes as bar_routes
from baz import routes as baz_routes
routes = (
bar_routes +
baz_routes)
for r in routes:
mod.add_url_rule(
r['rule'],
endpoint=r.get('endpoint', None),
view_func=r['view_func'],
**r.get('options', {}))
@conmute
Copy link

conmute commented Aug 8, 2016

Very helpfull example. I exemined your way of solving problem and came up to this solution:

"""
Application router decoretor.

Use this to append or get rout list for specific modules.
"""

from functools import wraps

ROUTES = dict()


def bluprint_add_routes(blueprint, routes):
    """Assign url route function configuration to given blueprint."""
    for route in routes:
        blueprint.add_url_rule(
            route['rule'],
            endpoint=route.get('endpoint', None),
            view_func=route['view_func'],
            **route.get('options', {}))


def get_routes(module):
    """Filter routes by given module name."""
    if module in ROUTES.keys():
        return list(ROUTES[module])
    else:
        return ()


def application_route(rule, **kargs):
    """Decorator function that collects application routes."""
    def wrapper(funcion):  # pylint: disable=missing-docstring

        if funcion.__module__ not in ROUTES.keys():
            ROUTES[funcion.__module__] = []

        ROUTES[funcion.__module__].append(dict(
            rule=rule,
            view_func=funcion,
            options=kargs,
        ))

        @wraps(funcion)
        def wrapped(*args, **kwargs):  # pylint: disable=missing-docstring
            return funcion(*args, **kwargs)
        return wrapped
    return wrapper

So you can do smth like this:

"""
Public module.

Handles requests for unathorised users.
"""

from flask import Blueprint
from app.utils.route import bluprint_add_routes
from app.public.pages import ROUTES as PAGE_ROUTES
from app.public.contact_us import ROUTES as CONTACT_US_ROUTES

BLUEPRINT = Blueprint('public', __name__,
                      template_folder='../templates/public')

bluprint_add_routes(BLUEPRINT, PAGE_ROUTES + CONTACT_US_ROUTES)
"""Public pages for unathorised users."""

from flask import render_template
from app.utils.route import application_route, get_routes


@application_route("/")
def home():
    """Show main landing page."""
    return render_template('home.jade', page=None)


@application_route("/<slug>")
def page(slug):
    """Show custom public page."""
    return render_template('page.jade', page=None)

ROUTES = get_routes("app.public.pages")

@cisdell
Copy link

cisdell commented Aug 19, 2023

cool

@Larsene
Copy link

Larsene commented Dec 1, 2023

why don't you simply use Nesting Blueprints ? https://flask.palletsprojects.com/en/3.0.x/blueprints/#nesting-blueprints ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment