Typorithm · easy

Flask: routes, endpoint names and HTTP methods

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: routes, endpoint names and HTTP methods

0%

Concept and contract

Generate URLs from endpoint names and keep method policy explicit.

A URL rule connects a path pattern, endpoint name and allowed methods. The integer converter constrains matching before the view receives the value, while url_for resolves the endpoint into a path.

An endpoint name is not necessarily the path or display title. Separating those concepts allows a path to move without rewriting every link that refers to the view.

Mechanism and worked example

The example validates the helper input, opens a short request context for URL generation and sends a request through the test client.

The example validates the helper input, opens a short request context for URL generation and sends a request through the test client. The view permits GET, with Flask providing normal HEAD and OPTIONS behavior.

POST is rejected before the view executes. The helper returns observed status and generated path, so both routing and method boundaries are visible to the checks.

Complete worked example

python

from flask import Flask, url_for
app = Flask(__name__)
app.config['TESTING'] = True
@app.get('/roles/<int:role_id>')
def detail(role_id):
    return {'id': role_id}

def visit(role_id, method='GET'):
    if type(role_id) is not int or role_id < 0:
        raise ValueError('nonnegative integer required')
    with app.test_request_context():
        path = url_for('detail', role_id=role_id)
    response = app.test_client().open(path, method=method)
    return {'path': path, 'status': response.status_code}
Reasoning
The example validates the helper input, opens a short request context for URL generation and sends a request through the test client. The view permits GET, with Flask providing normal HEAD and OPTIONS behavior.

Counterexamples and common mistakes

A manually constructed path can look correct while targeting a different route after a rename.

A manually constructed path can look correct while targeting a different route after a rename. The counterexample builds a path under another prefix, which receives 404.

Distinguish a missing route from a method rejection: the latter generally returns 405 for an otherwise matching path. Avoid catching both and returning a fabricated success response; that hides useful protocol information.

Counterexample: a runnable framework mistake

python

from flask import Flask, url_for
app = Flask(__name__)
app.config['TESTING'] = True
@app.get('/roles/<int:role_id>')
def detail(role_id):
    return {'id': role_id}

def visit(role_id, method='GET'):
    if type(role_id) is not int or role_id < 0:
        raise ValueError('nonnegative integer required')
    with app.test_request_context():
        path = f'/missing/{role_id}'
    response = app.test_client().open(path, method=method)
    return {'path': path, 'status': response.status_code}
Reasoning
A manually constructed path can look correct while targeting a different route after a rename. The counterexample builds a path under another prefix, which receives 404.

Independent practice: one bounded framework change

Move the public rule under /api/roles while retaining the endpoint name detail.

Move the public rule under /api/roles while retaining the endpoint name detail. Existing url_for callers should follow the change automatically.

Preserve the integer policy and GET-only behavior. This is a deliberately small refactor: do not introduce an API framework or authentication layer yet, and do not replace the endpoint reference with the new path string.

Step 1: Move the route to /api/roles without changing its endpoint name. Step 2: Edit the decorator rule only.

Practice starter: solve before reading the solution

python

from flask import Flask, url_for
app = Flask(__name__)
app.config['TESTING'] = True
@app.get('/roles/<int:role_id>')
def detail(role_id):
    return {'id': role_id}

def visit(role_id, method='GET'):
    # Remove this placeholder, then adapt the retained baseline:
    # Move the route to /api/roles without changing its endpoint name.
    raise NotImplementedError
    if type(role_id) is not int or role_id < 0:
        raise ValueError('nonnegative integer required')
    with app.test_request_context():
        path = url_for('detail', role_id=role_id)
    response = app.test_client().open(path, method=method)
    return {'path': path, 'status': response.status_code}
Reasoning
Move the route to /api/roles without changing its endpoint name. Edit the decorator rule only.
  • Hint 1: Keep url_for resolving detail.
  • Hint 2: Preserve method and input checks.

Solution, tests and trade-offs

Cases check two identifiers and a disallowed POST, and separately reject a boolean masquerading as an integer.

Cases check two identifiers and a disallowed POST, and separately reject a boolean masquerading as an integer. Practice expects the new prefix while keeping GET successful and POST rejected.

The same helper inputs must not be mutated. Together these cases distinguish correct URL generation from code that merely changes a visible label or ignores the supplied method.

Practice solution and acceptance checks

python

from flask import Flask, url_for
app = Flask(__name__)
app.config['TESTING'] = True
@app.get('/api/roles/<int:role_id>')
def detail(role_id):
    return {'id': role_id}

def visit(role_id, method='GET'):
    if type(role_id) is not int or role_id < 0:
        raise ValueError('nonnegative integer required')
    with app.test_request_context():
        path = url_for('detail', role_id=role_id)
    response = app.test_client().open(path, method=method)
    return {'path': path, 'status': response.status_code}
Reasoning
Cases check two identifiers and a disallowed POST, and separately reject a boolean masquerading as an integer. Practice expects the new prefix while keeping GET successful and POST rejected.

Interview reasoning and next step

Real link generation may also need external host, scheme and proxy configuration.

Real link generation may also need external host, scheme and proxy configuration. Those values require a trusted deployment boundary; request headers are not automatically trustworthy.

First become comfortable with local relative URLs, named endpoints and status distinctions. A later blueprint lesson adds namespacing, and the deployment lesson explains why SERVER_NAME is not a host-security allowlist in current Flask.

Optional stretch — after the core task works: Add a namespaced blueprint and compare generated URLs.

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-routing. 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.

Generate URLs from endpoint names and keep method policy explicit.