Typorithm · easy

Flask: blueprints and endpoint namespaces

pythonflaskindependent-practice
Saved on this device
Full lesson · 4 learning steps Open any exercise for focused practice
1

Step 1 of 4 · intro card

Flask: blueprints and endpoint namespaces

0%

Concept and contract

Organize related routes without confusing a blueprint with an application.

A blueprint records operations to apply when it is registered on an application. It is useful for a coherent group of routes, templates and related behavior, but it is not an independently serving application.

Its name prefixes endpoint identities. A URL prefix changes paths at registration time without requiring each view to know the deployment-specific prefix.

Mechanism and worked example

The factory constructs a roles blueprint, defines a detail view and registers the group under the supplied prefix.

The factory constructs a roles blueprint, defines a detail view and registers the group under the supplied prefix. URL generation uses roles.detail, not only detail.

Two factories can choose different prefixes while retaining the same logical view identity. The request helper verifies the generated path actually reaches the registered view instead of returning a plausible-looking string alone.

Complete worked example

python

from flask import Flask, Blueprint, url_for

def create_app(prefix):
    app = Flask(__name__)
    app.config['TESTING'] = True
    roles = Blueprint('roles', __name__)
    @roles.get('/<int:role_id>')
    def detail(role_id):
        return {'id': role_id}
    app.register_blueprint(roles, url_prefix=prefix)
    return app

def blueprint_path(prefix, role_id):
    app = create_app(prefix)
    with app.test_request_context():
        path = url_for('roles.detail', role_id=role_id)
    return {'path': path, 'status': app.test_client().get(path).status_code}
Reasoning
The factory constructs a roles blueprint, defines a detail view and registers the group under the supplied prefix. URL generation uses roles.detail, not only detail.

Counterexamples and common mistakes

The counterexample hard-codes /roles even when registration uses another prefix.

The counterexample hard-codes /roles even when registration uses another prefix. That path is wrong for the second application.

Another common error is omitting the blueprint namespace and receiving BuildError during URL generation. Keep endpoint naming explicit in shared templates, and do not register arbitrary user-supplied modules or prefixes as a substitute for trusted application configuration.

Counterexample: a runnable framework mistake

python

from flask import Flask, Blueprint, url_for

def create_app(prefix):
    app = Flask(__name__)
    app.config['TESTING'] = True
    roles = Blueprint('roles', __name__)
    @roles.get('/<int:role_id>')
    def detail(role_id):
        return {'id': role_id}
    app.register_blueprint(roles, url_prefix=prefix)
    return app

def blueprint_path(prefix, role_id):
    app = create_app(prefix)
    with app.test_request_context():
        path = f'/roles/{role_id}'
    return {'path': path, 'status': app.test_client().get(path).status_code}
Reasoning
The counterexample hard-codes /roles even when registration uses another prefix. That path is wrong for the second application.

Independent practice: one bounded framework change

Add a collection view at the blueprint root that returns an empty items list.

Add a collection view at the blueprint root that returns an empty items list. Generate its URL through roles.collection and include both collection and detail paths in the helper response.

Preserve the supplied registration prefix. This introduces one related endpoint and reinforces namespacing without requiring a database, pagination policy or cross-module dependency graph.

Step 1: Add a namespaced collection route and return its generated URL. Step 2: Define collection on the same blueprint.

Practice starter: solve before reading the solution

python

from flask import Flask, Blueprint, url_for

def create_app(prefix):
    app = Flask(__name__)
    app.config['TESTING'] = True
    roles = Blueprint('roles', __name__)
    @roles.get('/<int:role_id>')
    def detail(role_id):
        return {'id': role_id}
    app.register_blueprint(roles, url_prefix=prefix)
    return app

def blueprint_path(prefix, role_id):
    # Remove this placeholder, then adapt the retained baseline:
    # Add a namespaced collection route and return its generated URL.
    raise NotImplementedError
    app = create_app(prefix)
    with app.test_request_context():
        path = url_for('roles.detail', role_id=role_id)
    return {'path': path, 'status': app.test_client().get(path).status_code}
Reasoning
Add a namespaced collection route and return its generated URL. Define collection on the same blueprint.
  • Hint 1: Resolve roles.collection inside the request context.
  • Hint 2: Preserve prefix-dependent detail routing.

Solution, tests and trade-offs

Baseline fixtures register /roles and /api/roles and inspect real responses; a third prefix checks that neither path is assumed globally.

Baseline fixtures register /roles and /api/roles and inspect real responses; a third prefix checks that neither path is assumed globally. Practice checks the collection path under each prefix as well.

Observe the trailing slash explicitly rather than treating redirects as equivalent in every context. A write endpoint can be sensitive to redirect behavior and should have a deliberate canonical path.

Practice solution and acceptance checks

python

from flask import Flask, Blueprint, url_for

def create_app(prefix):
    app = Flask(__name__)
    app.config['TESTING'] = True
    roles = Blueprint('roles', __name__)
    @roles.get('/<int:role_id>')
    def detail(role_id):
        return {'id': role_id}
    @roles.get('/')
    def collection():
        return {'items': []}
    app.register_blueprint(roles, url_prefix=prefix)
    return app

def blueprint_path(prefix, role_id):
    app = create_app(prefix)
    with app.test_request_context():
        path = url_for('roles.detail', role_id=role_id)
        collection = url_for('roles.collection')
    return {'path': path, 'collection': collection, 'status': app.test_client().get(path).status_code}
Reasoning
Baseline fixtures register /roles and /api/roles and inspect real responses; a third prefix checks that neither path is assumed globally. Practice checks the collection path under each prefix as well.

Interview reasoning and next step

In a larger repository a blueprint can live in its own package with templates and extension integration.

In a larger repository a blueprint can live in its own package with templates and extension integration. Avoid import cycles by initializing extensions independently and binding them in the factory.

Application and request contexts still belong to Flask’s context system, not to the blueprint itself. Explain that distinction before moving code between modules so organization does not obscure runtime ownership.

Optional stretch — after the core task works: Move the blueprint into a package without a circular factory import.

Computer practice: https://applydjinn.com/typorithm/python-frameworks-lab-20261105.zip. Install the pinned dependencies in an isolated environment, run verify.py --track flask, then edit the retained exercise baseline and check it with --practice fl-blueprints. The lab uses owned in-memory databases, local framework clients and tiny CPU tensors. It never reads the working ApplyDjinn database, contacts production feeds or downloads models.

Organize related routes without confusing a blueprint with an application.